mirror of https://github.com/tooot-app/app
parent
d7d41a44c3
commit
29f2bf7457
|
@ -41,5 +41,10 @@ jobs:
|
|||
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
|
||||
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
|
||||
APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }}
|
||||
ANDROID_KEYSTORE: ${{ secrets.ANDROID_KEYSTORE }}
|
||||
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEYSTORE_ALIAS }}
|
||||
ANDROID_KEYSTORE_KEY_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_KEY_PASSWORD }}
|
||||
SUPPLY_JSON_KEY_DATA: ${{ secrets.SUPPLY_JSON_KEY_DATA }}
|
||||
FL_GITHUB_RELEASE_API_BEARER: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: yarn app:build
|
||||
|
|
18
Gemfile.lock
18
Gemfile.lock
|
@ -8,16 +8,16 @@ GEM
|
|||
atomos (0.1.3)
|
||||
aws-eventstream (1.1.0)
|
||||
aws-partitions (1.422.0)
|
||||
aws-sdk-core (3.111.2)
|
||||
aws-sdk-core (3.112.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.41.0)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sdk-kms (1.42.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.87.0)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sdk-s3 (1.88.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.2)
|
||||
|
@ -36,7 +36,7 @@ GEM
|
|||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.6)
|
||||
emoji_regex (3.2.1)
|
||||
excon (0.78.1)
|
||||
excon (0.79.0)
|
||||
faraday (1.3.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
|
@ -47,8 +47,8 @@ GEM
|
|||
faraday-net_http (1.0.1)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.1)
|
||||
fastlane (2.172.0)
|
||||
fastimage (2.2.2)
|
||||
fastlane (2.173.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
|
@ -86,6 +86,7 @@ GEM
|
|||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fastlane-plugin-json (1.0.0)
|
||||
fastlane-plugin-versioning_android (0.1.0)
|
||||
fastlane-plugin-yarn (1.2)
|
||||
gh_inspector (1.1.3)
|
||||
google-api-client (0.38.0)
|
||||
|
@ -199,6 +200,7 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
fastlane
|
||||
fastlane-plugin-json
|
||||
fastlane-plugin-versioning_android
|
||||
fastlane-plugin-yarn
|
||||
|
||||
BUNDLED WITH
|
||||
|
|
|
@ -135,8 +135,12 @@ android {
|
|||
applicationId 'com.xmflsct.app.tooot'
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 4
|
||||
versionName "0.1.0"
|
||||
versionCode 50
|
||||
versionName "0.2"
|
||||
manifestPlaceholders = [
|
||||
expoSDK: project.hasProperty('expoSDK') ? project.property('expoSDK') : "",
|
||||
releaseChannel: project.hasProperty('releaseChannel') ? project.property('releaseChannel') : "default"
|
||||
]
|
||||
}
|
||||
splits {
|
||||
abi {
|
||||
|
@ -161,7 +165,7 @@ android {
|
|||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://reactnative.dev/docs/signed-apk-android.
|
||||
signingConfig signingConfigs.debug
|
||||
// signingConfig signingConfigs.debug
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
}
|
||||
|
|
|
@ -1,26 +1,13 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xmflsct.app.tooot">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.xmflsct.app.tooot">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
|
@ -28,9 +15,11 @@
|
|||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@xmflsct/tooot"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="40.0.0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="${expoSDK}"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_RELEASE_CHANNEL" android:value="${releaseChannel}"/>
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
|
@ -57,6 +46,4 @@
|
|||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<application android:requestLegacyExternalStorage="true"/>
|
||||
</manifest>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
app_identifier "com.xmflsct.app.tooot"
|
||||
package_name "com.xmflsct.app.tooot"
|
|
@ -1,4 +1,4 @@
|
|||
fastlane_version "2.172.0"
|
||||
fastlane_version "2.173.0"
|
||||
skip_docs
|
||||
|
||||
ensure_env_vars(
|
||||
|
@ -15,7 +15,7 @@ case ENVIRONMENT
|
|||
when "development"
|
||||
GITHUB_RELEASE= ""
|
||||
when "staging"
|
||||
GITHUB_RELEASE = "v#{VERSION} (#{BUILD_NUMBER})"
|
||||
GITHUB_RELEASE = "v#{VERSION}(#{BUILD_NUMBER})"
|
||||
when "production"
|
||||
GITHUB_RELEASE = "v#{VERSION}"
|
||||
end
|
||||
|
@ -26,20 +26,23 @@ EXPO_PLIST = "./ios/tooot/Supporting/Expo.plist"
|
|||
|
||||
desc "IOS: Prepare app store"
|
||||
private_lane :prepare_appstore_ios do
|
||||
case ENVIRONMENT
|
||||
when "staging", "production"
|
||||
set_info_plist_value( path: INFO_PLIST, key: "CFBundleShortVersionString", value: VERSION )
|
||||
increment_build_number( xcodeproj: XCODEPROJ, build_number: BUILD_NUMBER )
|
||||
app_store_connect_api_key
|
||||
end
|
||||
end
|
||||
|
||||
desc 'IOS: Update version information'
|
||||
private_lane :update_versions_ios do
|
||||
set_info_plist_value( path: INFO_PLIST, key: "CFBundleShortVersionString", value: VERSION )
|
||||
desc 'IOS: Update expo information'
|
||||
private_lane :update_expo_ios do
|
||||
set_info_plist_value( path: EXPO_PLIST, key: "EXUpdatesSDKVersion", value: VERSIONS[:expo] )
|
||||
set_info_plist_value( path: EXPO_PLIST, key: "EXUpdatesReleaseChannel", value: RELEASE_CHANNEL )
|
||||
end
|
||||
|
||||
desc "ANDROID: Prepare play store"
|
||||
private_lane :prepare_playstore_android do
|
||||
android_set_version_name( version_name: VERSION, gradle_file: "./android/app/build.gradle" )
|
||||
android_set_version_code( version_code: BUILD_NUMBER, gradle_file: "./android/app/build.gradle" )
|
||||
end
|
||||
|
||||
desc "Create new GitHub release"
|
||||
private_lane :github_release do
|
||||
case ENVIRONMENT
|
||||
|
@ -67,8 +70,7 @@ desc "Build and deploy iOS app"
|
|||
private_lane :build_ios do
|
||||
BUILD_DIRECTORY = "./ios/build"
|
||||
|
||||
update_versions_ios
|
||||
prepare_appstore_ios
|
||||
update_expo_ios
|
||||
setup_ci
|
||||
|
||||
case ENVIRONMENT
|
||||
|
@ -77,6 +79,7 @@ private_lane :build_ios do
|
|||
build_ios_app( export_method: "development", output_directory: BUILD_DIRECTORY, output_name: "#{VERSION}-#{BUILD_NUMBER}" )
|
||||
install_on_device( skip_wifi: true )
|
||||
when "staging"
|
||||
prepare_appstore_ios
|
||||
match( type: "appstore", readonly: true )
|
||||
build_ios_app( export_method: "app-store" )
|
||||
upload_to_testflight(
|
||||
|
@ -86,6 +89,7 @@ private_lane :build_ios do
|
|||
changelog: "Ready for testing"
|
||||
)
|
||||
when "production"
|
||||
prepare_appstore_ios
|
||||
match( type: "appstore", readonly: true )
|
||||
build_ios_app( export_method: "app-store" )
|
||||
end
|
||||
|
@ -93,32 +97,43 @@ end
|
|||
|
||||
desc "Build and deploy Android app"
|
||||
private_lane :build_android do
|
||||
sh("echo #{ENV["ANDROID_KEYSTORE"]} | base64 -d | tee #{File.expand_path('..', Dir.pwd)}/android/tooot.jks >/dev/null", log: false)
|
||||
|
||||
case ENVIRONMENT
|
||||
when "development"
|
||||
build_android_app(
|
||||
task: 'assemble',
|
||||
build_type: 'Debug',
|
||||
build_type: 'debug',
|
||||
project_dir: "./android"
|
||||
)
|
||||
adb(
|
||||
command: "install #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]}"
|
||||
)
|
||||
when "staging"
|
||||
prepare_playstore_android
|
||||
build_android_app(
|
||||
task: 'clean bundle',
|
||||
build_type: 'release',
|
||||
project_dir: "./android",
|
||||
print_command: false,
|
||||
print_command_output: false,
|
||||
properties: {
|
||||
"android.injected.signing.store.file" => "keystore.jks",
|
||||
"android.injected.signing.store.password" => "store_password",
|
||||
"android.injected.signing.key.alias" => "key_alias",
|
||||
"android.injected.signing.key.password" => "key_password",
|
||||
"expoSDK" => VERSIONS[:expo],
|
||||
"releaseChannel" => RELEASE_CHANNEL,
|
||||
"android.injected.signing.store.file" => "#{File.expand_path('..', Dir.pwd)}/android/tooot.jks",
|
||||
"android.injected.signing.store.password" => ENV["ANDROID_KEYSTORE_PASSWORD"],
|
||||
"android.injected.signing.key.alias" => ENV["ANDROID_KEYSTORE_ALIAS"],
|
||||
"android.injected.signing.key.password" => ENV["ANDROID_KEYSTORE_KEY_PASSWORD"],
|
||||
}
|
||||
)
|
||||
puts lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
|
||||
when "staging"
|
||||
match( type: "appstore", readonly: true )
|
||||
build_ios_app( export_method: "app-store" )
|
||||
upload_to_testflight(
|
||||
demo_account_required: true,
|
||||
distribute_external: true,
|
||||
groups: "内测用户",
|
||||
changelog: "Ready for testing"
|
||||
upload_to_play_store(
|
||||
track: "alpha",
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_changelogs: true,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true
|
||||
)
|
||||
when "production"
|
||||
match( type: "appstore", readonly: true )
|
||||
build_ios_app( export_method: "app-store" )
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -129,7 +144,7 @@ lane :build do
|
|||
else
|
||||
puts("Release #{GITHUB_RELEASE} does not exist. Create new release as well as new native build.")
|
||||
build_ios
|
||||
# build_android
|
||||
build_android
|
||||
case ENVIRONMENT
|
||||
when "staging"
|
||||
github_release
|
||||
|
@ -137,6 +152,6 @@ lane :build do
|
|||
github_release
|
||||
end
|
||||
end
|
||||
# expo_release
|
||||
expo_release
|
||||
rocket
|
||||
end
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
gem 'fastlane-plugin-yarn'
|
||||
gem 'fastlane-plugin-json'
|
||||
gem 'fastlane-plugin-versioning_android'
|
||||
|
|
|
@ -54,6 +54,8 @@ PODS:
|
|||
- UMPermissionsInterface
|
||||
- EXRandom (10.0.0):
|
||||
- React-Core
|
||||
- EXScreenCapture (3.0.0):
|
||||
- UMCore
|
||||
- EXSecureStore (9.3.0):
|
||||
- UMCore
|
||||
- EXSplashScreen (0.8.1):
|
||||
|
@ -465,7 +467,7 @@ PODS:
|
|||
- UMBarCodeScannerInterface (5.4.0)
|
||||
- UMCameraInterface (5.4.0)
|
||||
- UMConstantsInterface (5.4.0)
|
||||
- UMCore (6.0.0)
|
||||
- UMCore (7.0.0)
|
||||
- UMFaceDetectorInterface (5.4.0)
|
||||
- UMFileSystemInterface (5.4.0)
|
||||
- UMFontInterface (5.4.0)
|
||||
|
@ -501,6 +503,7 @@ DEPENDENCIES:
|
|||
- EXLocation (from `../node_modules/expo-location/ios`)
|
||||
- EXPermissions (from `../node_modules/expo-permissions/ios`)
|
||||
- EXRandom (from `../node_modules/expo-random/ios`)
|
||||
- EXScreenCapture (from `../node_modules/expo-screen-capture/ios`)
|
||||
- EXSecureStore (from `../node_modules/expo-secure-store/ios`)
|
||||
- EXSplashScreen (from `../node_modules/expo-splash-screen/ios`)
|
||||
- EXSQLite (from `../node_modules/expo-sqlite/ios`)
|
||||
|
@ -554,7 +557,7 @@ DEPENDENCIES:
|
|||
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
||||
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
||||
- UMConstantsInterface (from `../node_modules/unimodules-constants-interface/ios`)
|
||||
- "UMCore (from `../node_modules/@unimodules/core/ios`)"
|
||||
- "UMCore (from `../node_modules/expo-screen-capture/node_modules/@unimodules/core/ios`)"
|
||||
- UMFaceDetectorInterface (from `../node_modules/unimodules-face-detector-interface/ios`)
|
||||
- UMFileSystemInterface (from `../node_modules/unimodules-file-system-interface/ios`)
|
||||
- UMFontInterface (from `../node_modules/unimodules-font-interface/ios`)
|
||||
|
@ -626,6 +629,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/expo-permissions/ios"
|
||||
EXRandom:
|
||||
:path: "../node_modules/expo-random/ios"
|
||||
EXScreenCapture:
|
||||
:path: "../node_modules/expo-screen-capture/ios"
|
||||
EXSecureStore:
|
||||
:path: "../node_modules/expo-secure-store/ios"
|
||||
EXSplashScreen:
|
||||
|
@ -729,7 +734,7 @@ EXTERNAL SOURCES:
|
|||
UMConstantsInterface:
|
||||
:path: "../node_modules/unimodules-constants-interface/ios"
|
||||
UMCore:
|
||||
:path: "../node_modules/@unimodules/core/ios"
|
||||
:path: "../node_modules/expo-screen-capture/node_modules/@unimodules/core/ios"
|
||||
UMFaceDetectorInterface:
|
||||
:path: "../node_modules/unimodules-face-detector-interface/ios"
|
||||
UMFileSystemInterface:
|
||||
|
@ -771,6 +776,7 @@ SPEC CHECKSUMS:
|
|||
EXLocation: d55e2a37f61bcfb4eba9c813b3f4621d896c4c00
|
||||
EXPermissions: 17d4846ad1880f6891c74ae58ca1acb43e47ed47
|
||||
EXRandom: d7e0f3dd64810aabd27d59f8ecffee359177e2c3
|
||||
EXScreenCapture: 5b8447139e56e2b922e93ccdc7c773c103fb44fd
|
||||
EXSecureStore: 1b571851e6068b30b8ec097be848a04603c03bae
|
||||
EXSplashScreen: 8c7c1112ce7611a853486af4737fe2298eda7657
|
||||
EXSQLite: bda6a286dded0637bb312ee781239dcca163ff4b
|
||||
|
@ -838,7 +844,7 @@ SPEC CHECKSUMS:
|
|||
UMBarCodeScannerInterface: 3f6c1b09ef4b867ce752b8c0b3893bcf9cd85f32
|
||||
UMCameraInterface: d516032121192fee9a6c93bdfff0bb2cc7282796
|
||||
UMConstantsInterface: 6825ea3832d26ed392ca6eff2df84edd69968fd0
|
||||
UMCore: 97ba5041c9c92317ce61739f6d126a692c8ef4a8
|
||||
UMCore: a882a262c77a535d46b058c150f957eface073f4
|
||||
UMFaceDetectorInterface: 60b36b07faa539205efce30b20c192e058b31c23
|
||||
UMFileSystemInterface: ab01294ce58a3c773aefb4a5b131ce589c199559
|
||||
UMFontInterface: 85fe1b845fb7caab45e04d9ce47e1677a5ce90a5
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"expo-linking": "~2.0.1",
|
||||
"expo-localization": "~9.1.0",
|
||||
"expo-random": "~10.0.0",
|
||||
"expo-screen-capture": "^3.0.0",
|
||||
"expo-secure-store": "~9.3.0",
|
||||
"expo-splash-screen": "~0.8.1",
|
||||
"expo-status-bar": "~1.0.3",
|
||||
|
@ -108,7 +109,7 @@
|
|||
"versions": {
|
||||
"native": "210201",
|
||||
"major": 0,
|
||||
"minor": 2,
|
||||
"minor": 3,
|
||||
"patch": 0,
|
||||
"expo": "40.0.0"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import client from '@api/client'
|
||||
import { HeaderLeft } from '@components/Header'
|
||||
import { HeaderCenter, HeaderLeft } from '@components/Header'
|
||||
import { toast, toastConfig } from '@components/toast'
|
||||
import {
|
||||
NavigationContainer,
|
||||
|
@ -17,9 +17,10 @@ import {
|
|||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { themes } from '@utils/styles/themes'
|
||||
import * as Analytics from 'expo-firebase-analytics'
|
||||
import { addScreenshotListener } from 'expo-screen-capture'
|
||||
import React, { createRef, useCallback, useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Platform, StatusBar } from 'react-native'
|
||||
import { Alert, Platform, StatusBar } from 'react-native'
|
||||
import Toast from 'react-native-toast-message'
|
||||
import { createSharedElementStackNavigator } from 'react-navigation-shared-element'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
@ -33,6 +34,7 @@ export interface Props {
|
|||
export const navigationRef = createRef<NavigationContainerRef>()
|
||||
|
||||
const Index: React.FC<Props> = ({ localCorrupt }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const dispatch = useDispatch()
|
||||
const localActiveIndex = useSelector(getLocalActiveIndex)
|
||||
const { mode, theme } = useTheme()
|
||||
|
@ -56,8 +58,18 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
|||
// }
|
||||
// }, [isConnected, firstRender])
|
||||
|
||||
// Prevent screenshot alert
|
||||
useEffect(() => {
|
||||
const screenshotListener = addScreenshotListener(() =>
|
||||
Alert.alert(t('screenshot.title'), t('screenshot.message'), [
|
||||
{ text: t('screenshot.button'), style: 'destructive' }
|
||||
])
|
||||
)
|
||||
Platform.OS === 'ios' && screenshotListener
|
||||
return () => screenshotListener.remove()
|
||||
}, [])
|
||||
|
||||
// On launch display login credentials corrupt information
|
||||
const { t } = useTranslation('common')
|
||||
useEffect(() => {
|
||||
const showLocalCorrect = localCorrupt
|
||||
? toast({
|
||||
|
@ -153,7 +165,12 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
|||
component={ScreenAnnouncements}
|
||||
options={{
|
||||
gestureEnabled: false,
|
||||
title: t('sharedAnnouncements:heading'),
|
||||
headerTitle: t('sharedAnnouncements:heading'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => (
|
||||
<HeaderCenter content={t('sharedAnnouncements:heading')} />
|
||||
)
|
||||
}),
|
||||
headerTransparent: true,
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
|
|
|
@ -3,7 +3,6 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useEffect, useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
Pressable,
|
||||
StyleProp,
|
||||
|
@ -49,8 +48,7 @@ const Button: React.FC<Props> = ({
|
|||
overlay = false,
|
||||
onPress
|
||||
}) => {
|
||||
const { i18n } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const { mode, theme } = useTheme()
|
||||
|
||||
const mounted = useRef(false)
|
||||
useEffect(() => {
|
||||
|
@ -67,7 +65,7 @@ const Button: React.FC<Props> = ({
|
|||
<Chase size={StyleConstants.Font.Size[size]} color={theme.secondary} />
|
||||
</View>
|
||||
),
|
||||
[theme]
|
||||
[mode]
|
||||
)
|
||||
|
||||
const colorContent = useMemo(() => {
|
||||
|
@ -88,7 +86,7 @@ const Button: React.FC<Props> = ({
|
|||
}
|
||||
}
|
||||
}
|
||||
}, [theme, disabled])
|
||||
}, [mode, disabled])
|
||||
const colorBorder = useMemo(() => {
|
||||
if (active) {
|
||||
return theme.blue
|
||||
|
@ -103,14 +101,14 @@ const Button: React.FC<Props> = ({
|
|||
}
|
||||
}
|
||||
}
|
||||
}, [theme, loading, disabled])
|
||||
}, [mode, loading, disabled])
|
||||
const colorBackground = useMemo(() => {
|
||||
if (overlay) {
|
||||
return theme.backgroundOverlay
|
||||
} else {
|
||||
return theme.background
|
||||
}
|
||||
}, [theme])
|
||||
}, [mode])
|
||||
|
||||
const children = useMemo(() => {
|
||||
switch (type) {
|
||||
|
@ -147,7 +145,7 @@ const Button: React.FC<Props> = ({
|
|||
</>
|
||||
)
|
||||
}
|
||||
}, [i18n.language, theme, content, loading, disabled, active])
|
||||
}, [mode, content, loading, disabled, active])
|
||||
|
||||
enum spacingMapping {
|
||||
XS = 'S',
|
||||
|
|
|
@ -28,10 +28,7 @@ const ComponentHashtag: React.FC<Props> = ({
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
style={[styles.itemDefault, { borderBottomColor: theme.border }]}
|
||||
onPress={customOnPress || onPress}
|
||||
>
|
||||
<Pressable style={styles.itemDefault} onPress={customOnPress || onPress}>
|
||||
<Text style={[styles.itemHashtag, { color: theme.primary }]}>
|
||||
#{hashtag.name}
|
||||
</Text>
|
||||
|
@ -41,8 +38,7 @@ const ComponentHashtag: React.FC<Props> = ({
|
|||
|
||||
const styles = StyleSheet.create({
|
||||
itemDefault: {
|
||||
padding: StyleConstants.Spacing.S * 1.5,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth
|
||||
padding: StyleConstants.Spacing.S * 1.5
|
||||
},
|
||||
itemHashtag: {
|
||||
...StyleConstants.FontStyle.M
|
||||
|
|
|
@ -33,7 +33,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||
disableHeaderImage,
|
||||
goBack = false
|
||||
}) => {
|
||||
const { t } = useTranslation('componentInstance')
|
||||
const { t, i18n } = useTranslation('componentInstance')
|
||||
const { theme } = useTheme()
|
||||
const navigation = useNavigation()
|
||||
|
||||
|
@ -136,7 +136,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||
case 'remote':
|
||||
return t('server.button.remote')
|
||||
}
|
||||
}, [])
|
||||
}, [i18n.language])
|
||||
|
||||
const requestAuth = useMemo(() => {
|
||||
if (
|
||||
|
|
|
@ -164,7 +164,13 @@ const Timeline: React.FC<Props> = ({
|
|||
<RefreshControl
|
||||
{...(Platform.OS === 'android' && { enabled: true })}
|
||||
refreshing={
|
||||
isSwipeDown.current && isFetching && !isFetchingNextPage && !isLoading
|
||||
Platform.OS === 'android'
|
||||
? (isSwipeDown.current && isFetching && !isFetchingNextPage) ||
|
||||
isLoading
|
||||
: isSwipeDown.current &&
|
||||
isFetching &&
|
||||
!isFetchingNextPage &&
|
||||
!isLoading
|
||||
}
|
||||
onRefresh={() => {
|
||||
isSwipeDown.current = true
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
export default {
|
||||
screenshot: {
|
||||
title: 'Privacy Protection',
|
||||
message: 'Please do not disclose other user\'s identity, such as username, avatar, etc. Thank you!',
|
||||
button: 'Confirm'
|
||||
},
|
||||
index: {
|
||||
localCorrupt: 'Login expired, please login again'
|
||||
},
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export default {
|
||||
heading: 'Direct messages'
|
||||
heading: 'Discussions'
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
export default {
|
||||
screenshot: {
|
||||
title: '隐私保护',
|
||||
message: '请确保不要泄露其它用户的敏感信息,例如用户名、头像等,谢谢!',
|
||||
button: '好的'
|
||||
},
|
||||
index: {
|
||||
localCorrupt: '登录已过期,请重新登录'
|
||||
},
|
||||
|
|
|
@ -231,6 +231,7 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
|
|||
<KeyboardAvoidingView
|
||||
style={styles.base}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
keyboardVerticalOffset={Platform.OS === 'android' ? 23 : 0}
|
||||
>
|
||||
<SafeAreaView
|
||||
style={styles.base}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { forEach, groupBy, sortBy } from 'lodash'
|
||||
import React, { useCallback, useContext, useEffect, useMemo } from 'react'
|
||||
import { FlatList, Image, StyleSheet, View } from 'react-native'
|
||||
import { FlatList, StyleSheet, View } from 'react-native'
|
||||
import { Chase } from 'react-native-animated-spinkit'
|
||||
import ComposeActions from './Root/Actions'
|
||||
import ComposePosting from './Posting'
|
||||
|
@ -70,7 +70,7 @@ const ComposeRoot: React.FC = () => {
|
|||
const listItem = useCallback(
|
||||
({ item, index }) => (
|
||||
<ComposeRootSuggestion
|
||||
key={(item.id || item.name) + index}
|
||||
key={index}
|
||||
item={item}
|
||||
composeState={composeState}
|
||||
composeDispatch={composeDispatch}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import analytics from '@components/analytics'
|
||||
import { HeaderRight } from '@components/Header'
|
||||
import { HeaderCenter, HeaderRight } from '@components/Header'
|
||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||
import { StackScreenProps } from '@react-navigation/stack'
|
||||
import CameraRoll from '@react-native-community/cameraroll'
|
||||
|
@ -8,13 +8,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
|
|||
import { findIndex } from 'lodash'
|
||||
import React, { useCallback, useLayoutEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
PermissionsAndroid,
|
||||
Platform,
|
||||
Share,
|
||||
StyleSheet,
|
||||
Text
|
||||
} from 'react-native'
|
||||
import { PermissionsAndroid, Platform, Share, StyleSheet } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import ImageViewer from 'react-native-image-zoom-viewer'
|
||||
import { SharedElement } from 'react-navigation-shared-element'
|
||||
|
@ -107,11 +101,9 @@ const ScreenImagesViewer = React.memo(
|
|||
() =>
|
||||
navigation.setOptions({
|
||||
headerTitle: () => (
|
||||
<Text
|
||||
style={[styles.headerCenter, { color: theme.primaryOverlay }]}
|
||||
>
|
||||
{currentIndex + 1} / {imageUrls.length}
|
||||
</Text>
|
||||
<HeaderCenter
|
||||
content={`${currentIndex + 1} / ${imageUrls.length}`}
|
||||
/>
|
||||
),
|
||||
headerRight: () => (
|
||||
<HeaderRight
|
||||
|
|
|
@ -9,8 +9,8 @@ import ScreenMeSwitchRoot from './Switch/Root'
|
|||
const Stack = createNativeStackNavigator()
|
||||
|
||||
const ScreenMeSwitch: React.FC<StackScreenProps<
|
||||
Nav.MeStackParamList,
|
||||
'Screen-Me-Switch'
|
||||
Nav.TabMeStackParamList,
|
||||
'Tab-Me-Switch'
|
||||
>> = ({ navigation }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
|
|
|
@ -45,8 +45,8 @@ const AccountButton: React.FC<Props> = ({ instance, disabled = false }) => {
|
|||
onPress={() => {
|
||||
haptics('Light')
|
||||
analytics('switch_existing_press')
|
||||
dispatch(localUpdateActiveIndex(instance))
|
||||
queryClient.clear()
|
||||
dispatch(localUpdateActiveIndex(instance))
|
||||
navigation.goBack()
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -2,8 +2,6 @@ import Timeline from '@components/Timelines/Timeline'
|
|||
import React from 'react'
|
||||
import { SharedHashtagProp } from './sharedScreens'
|
||||
|
||||
// Show remote hashtag? Only when private, show local version?
|
||||
|
||||
const TabSharedHashtag: React.FC<SharedHashtagProp> = ({
|
||||
route: {
|
||||
params: { hashtag }
|
||||
|
|
|
@ -136,7 +136,14 @@ const sharedScreens = (
|
|||
name='Tab-Shared-Hashtag'
|
||||
component={TabSharedHashtag}
|
||||
options={({ route, navigation }: SharedHashtagProp) => ({
|
||||
title: `#${decodeURIComponent(route.params.hashtag)}`,
|
||||
headerTitle: `#${decodeURIComponent(route.params.hashtag)}`,
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => (
|
||||
<HeaderCenter
|
||||
content={`#${decodeURIComponent(route.params.hashtag)}`}
|
||||
/>
|
||||
)
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>,
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { preventScreenCaptureAsync } from 'expo-screen-capture'
|
||||
import log from './log'
|
||||
|
||||
const preventScreenshot = () => {
|
||||
log('log', 'Screenshot', 'preventing')
|
||||
preventScreenCaptureAsync()
|
||||
}
|
||||
|
||||
export default preventScreenshot
|
14
yarn.lock
14
yarn.lock
|
@ -2630,6 +2630,13 @@
|
|||
dependencies:
|
||||
compare-versions "^3.4.0"
|
||||
|
||||
"@unimodules/core@~7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@unimodules/core/-/core-7.0.0.tgz#0311a9c7c0a661368ceef8891f758eb2e166bdf4"
|
||||
integrity sha512-hKxNN6ad2VmmJqB3i1C8IJe27TcchY7YAKpkQhshjPxso61f7iM7AUFeG4vcU1vPH5d/X4Vk1ds8bWxaxg7nnw==
|
||||
dependencies:
|
||||
compare-versions "^3.4.0"
|
||||
|
||||
"@unimodules/react-native-adapter@~5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@unimodules/react-native-adapter/-/react-native-adapter-5.7.0.tgz#c5b7c660c5c69e77a7baeaed62be73cfe18dd7b0"
|
||||
|
@ -4565,6 +4572,13 @@ expo-random@~10.0.0:
|
|||
dependencies:
|
||||
base64-js "^1.3.0"
|
||||
|
||||
expo-screen-capture@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/expo-screen-capture/-/expo-screen-capture-3.0.0.tgz#c35a94acca4274a0ea67c8e09e0b39c19fecc0a6"
|
||||
integrity sha512-TXLIH/NcuMPNT5dUGKWdwZtBhA+N17A3cFk1cICHlalerGU5uyRYJalaJAY+U+WwAEpOAIehfonv1Qa87W58Nw==
|
||||
dependencies:
|
||||
"@unimodules/core" "~7.0.0"
|
||||
|
||||
expo-secure-store@~9.3.0:
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/expo-secure-store/-/expo-secure-store-9.3.0.tgz#b716d5d115cc50a34037d1afef84fe4b8ea0745c"
|
||||
|
|
Loading…
Reference in New Issue