Test release

Added screenshot package
This commit is contained in:
Zhiyuan Zheng 2021-02-05 01:13:57 +01:00
parent d7d41a44c3
commit 29f2bf7457
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
26 changed files with 179 additions and 109 deletions

View File

@ -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

View File

@ -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

View File

@ -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"
}
@ -218,4 +222,4 @@ task copyDownloadableDepsToLibs(type: Copy) {
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'

View File

@ -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>

View File

@ -1 +1,2 @@
app_identifier "com.xmflsct.app.tooot"
app_identifier "com.xmflsct.app.tooot"
package_name "com.xmflsct.app.tooot"

View File

@ -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"
increment_build_number( xcodeproj: XCODEPROJ, build_number: BUILD_NUMBER )
app_store_connect_api_key
end
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
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

View File

@ -4,3 +4,4 @@
gem 'fastlane-plugin-yarn'
gem 'fastlane-plugin-json'
gem 'fastlane-plugin-versioning_android'

View File

@ -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

View File

@ -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,8 +109,8 @@
"versions": {
"native": "210201",
"major": 0,
"minor": 2,
"minor": 3,
"patch": 0,
"expo": "40.0.0"
}
}
}

View File

@ -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

View File

@ -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',

View File

@ -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

View File

@ -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 (

View File

@ -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

View File

@ -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'
},

View File

@ -1,3 +1,3 @@
export default {
heading: 'Direct messages'
heading: 'Discussions'
}

View File

@ -1,4 +1,9 @@
export default {
screenshot: {
title: '隐私保护',
message: '请确保不要泄露其它用户的敏感信息,例如用户名、头像等,谢谢!',
button: '好的'
},
index: {
localCorrupt: '登录已过期,请重新登录'
},

View File

@ -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}

View File

@ -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}

View File

@ -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

View File

@ -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 (

View File

@ -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()
}}
/>

View File

@ -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 }

View File

@ -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()} />
})}
/>,

View File

@ -0,0 +1,9 @@
import { preventScreenCaptureAsync } from 'expo-screen-capture'
import log from './log'
const preventScreenshot = () => {
log('log', 'Screenshot', 'preventing')
preventScreenCaptureAsync()
}
export default preventScreenshot

View File

@ -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"