Android build success

This commit is contained in:
Zhiyuan Zheng 2021-01-30 02:03:39 +01:00
parent 247f7a7982
commit 253ddee319
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
12 changed files with 86 additions and 592 deletions

1
.gitignore vendored
View File

@ -51,6 +51,7 @@ build/
.gradle
local.properties
*.iml
*.hprof
# node.js
#

View File

@ -0,0 +1,37 @@
package com.xmflsct.app.tooot.generated;
import java.util.Arrays;
import java.util.List;
import org.unimodules.core.interfaces.Package;
public class BasePackageList {
public List<Package> getPackageList() {
return Arrays.<Package>asList(
new expo.modules.application.ApplicationPackage(),
new expo.modules.av.AVPackage(),
new expo.modules.constants.ConstantsPackage(),
new expo.modules.crypto.CryptoPackage(),
new expo.modules.device.DevicePackage(),
new expo.modules.errorrecovery.ErrorRecoveryPackage(),
new expo.modules.filesystem.FileSystemPackage(),
new expo.modules.firebase.analytics.FirebaseAnalyticsPackage(),
new expo.modules.firebase.core.FirebaseCorePackage(),
new expo.modules.font.FontLoaderPackage(),
new expo.modules.haptics.HapticsPackage(),
new expo.modules.imageloader.ImageLoaderPackage(),
new expo.modules.imagepicker.ImagePickerPackage(),
new expo.modules.keepawake.KeepAwakePackage(),
new expo.modules.lineargradient.LinearGradientPackage(),
new expo.modules.localization.LocalizationPackage(),
new expo.modules.location.LocationPackage(),
new expo.modules.permissions.PermissionsPackage(),
new expo.modules.securestore.SecureStorePackage(),
new expo.modules.splashscreen.SplashScreenPackage(),
new expo.modules.sqlite.SQLitePackage(),
new expo.modules.storereview.StoreReviewPackage(),
new expo.modules.updates.UpdatesPackage(),
new expo.modules.videothumbnails.VideoThumbnailsPackage(),
new expo.modules.webbrowser.WebBrowserPackage()
);
}
}

View File

@ -26,4 +26,9 @@ android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.54.0
FLIPPER_VERSION=0.54.0
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true

View File

@ -36,15 +36,6 @@ export default (): ExpoConfig => ({
}
]
},
ios: {
buildNumber: '4',
config: { usesNonExemptEncryption: false },
bundleIdentifier: 'com.xmflsct.app.tooot',
googleServicesFile: './configs/GoogleService-Info.plist',
infoPlist: {
CFBundleAllowMixedLocalizations: true
}
},
locales: {
en: './src/i18n/en/system.json',
zh: './src/i18n/zh-Hans/system.json'
@ -54,18 +45,5 @@ export default (): ExpoConfig => ({
package: 'com.xmflsct.app.tooot',
googleServicesFile: './configs/google-services.json',
permissions: ['CAMERA', 'VIBRATE']
},
web: {
config: {
firebase: {
apiKey: 'AIzaSyAnvo0jyD1WB0tv2FLenz-CSDS-RgaWWR4',
authDomain: 'xmflsct-mastodon-app.firebaseapp.com',
projectId: 'xmflsct-mastodon-app',
storageBucket: 'xmflsct-mastodon-app.appspot.com',
messagingSenderId: '661638997772',
appId: '1:661638997772:web:1e7aab28be7dc06d9f8b29',
measurementId: 'G-3J0FS8WV5J'
}
}
}
})

View File

@ -212,9 +212,6 @@ const Timeline: React.FC<Props> = ({
ListEmptyComponent={flItemEmptyComponent}
{...(!disableRefresh && { refreshControl })}
ItemSeparatorComponent={ItemSeparatorComponent}
{...(queryKey &&
queryKey[1].page === 'RemotePublic' &&
!publicRemoteNotice && { ListHeaderComponent })}
{...(toot && isSuccess && { onScrollToIndexFailed })}
maintainVisibleContentPosition={{
minIndexForVisible: 0,

View File

@ -1,130 +0,0 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { toast } from '@components/toast'
import {
MutationVarsTimelineUpdateAccountProperty,
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useQueryClient } from 'react-query'
export interface Props {
queryKey?: QueryKeyTimeline
account: Mastodon.Account
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
}
const HeaderActionsAccount: React.FC<Props> = ({
queryKey,
account,
setBottomSheetVisible
}) => {
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
const mutateion = useTimelineMutation({
queryClient,
onSuccess: (_, params) => {
const theParams = params as MutationVarsTimelineUpdateAccountProperty
haptics('Success')
toast({
type: 'success',
message: t('common:toastMessage.success.message', {
function: t(
`shared.header.actions.account.${theParams.payload.property}.function`,
{
acct: account.acct
}
)
})
})
},
onError: (err: any, params) => {
const theParams = params as MutationVarsTimelineUpdateAccountProperty
haptics('Error')
toast({
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(
`shared.header.actions.account.${theParams.payload.property}.function`
)
}),
...(err.status &&
typeof err.status === 'number' &&
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
})
},
onSettled: () => {
queryKey && queryClient.invalidateQueries(queryKey)
}
})
return (
<MenuContainer>
<MenuHeader heading={t('shared.header.actions.account.heading')} />
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_account_mute_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutateion.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'mute' }
})
}}
iconFront='EyeOff'
title={t('shared.header.actions.account.mute.button', {
acct: account.acct
})}
/>
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_account_block_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutateion.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'block' }
})
}}
iconFront='XCircle'
title={t('shared.header.actions.account.block.button', {
acct: account.acct
})}
/>
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_account_reports_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutateion.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'reports' }
})
}}
iconFront='Flag'
title={t('shared.header.actions.account.reports.button', {
acct: account.acct
})}
/>
</MenuContainer>
)
}
export default HeaderActionsAccount

View File

@ -1,87 +0,0 @@
import analytics from '@components/analytics'
import MenuContainer from '@components/Menu/Container'
import MenuHeader from '@components/Menu/Header'
import MenuRow from '@components/Menu/Row'
import { toast } from '@components/toast'
import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
import { useQueryClient } from 'react-query'
export interface Props {
queryKey: QueryKeyTimeline
domain: string
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
}
const HeaderActionsDomain: React.FC<Props> = ({
queryKey,
domain,
setBottomSheetVisible
}) => {
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
const mutation = useTimelineMutation({
queryClient,
onSettled: () => {
toast({
type: 'success',
message: t('common:toastMessage.success.message', {
function: t(`shared.header.actions.domain.block.function`)
})
})
queryClient.invalidateQueries(queryKey)
}
})
return (
<MenuContainer>
<MenuHeader heading={t(`shared.header.actions.domain.heading`)} />
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_domain_block_press', {
page: queryKey[1].page
})
Alert.alert(
t('shared.header.actions.domain.alert.title', { domain }),
t('shared.header.actions.domain.alert.message'),
[
{
text: t('shared.header.actions.domain.alert.buttons.cancel'),
style: 'cancel'
},
{
text: t('shared.header.actions.domain.alert.buttons.confirm'),
style: 'destructive',
onPress: () => {
analytics(
'timeline_shared_headeractions_domain_block_confirm',
{
page: queryKey && queryKey[1].page
}
)
setBottomSheetVisible(false)
mutation.mutate({
type: 'domainBlock',
queryKey,
domain: domain
})
}
}
]
)
}}
iconFront='CloudOff'
title={t(`shared.header.actions.domain.block.button`, {
domain
})}
/>
</MenuContainer>
)
}
export default HeaderActionsDomain

View File

@ -1,110 +0,0 @@
import analytics from '@components/analytics'
import BottomSheet from '@screens/Tabs/Shared/node_modules/@screens/Actions/BottomSheet'
import Icon from '@components/Icon'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo, useState } from 'react'
import { Pressable, StyleSheet } from 'react-native'
import { useSelector } from 'react-redux'
import HeaderActionsAccount from './Account'
import HeaderActionsDomain from './Domain'
import HeaderActionsShare from './Share'
import HeaderActionsStatus from './Status'
export interface Props {
queryKey: QueryKeyTimeline
status: Mastodon.Status
url?: string
type?: 'status' | 'account'
}
const HeaderActions = React.memo(
({ queryKey, status, url, type }: Props) => {
const { theme } = useTheme()
const localAccount = useSelector(getLocalAccount)
const sameAccount = localAccount?.id === status.account.id
const localDomain = useSelector(getLocalUrl)
const statusDomain = status.uri
? status.uri.split(new RegExp(/\/\/(.*?)\//))[1]
: ''
const sameDomain = localDomain === statusDomain
const [modalVisible, setBottomSheetVisible] = useState(false)
const onPress = useCallback(() => {
analytics('bottomsheet_open_press', {
page: queryKey[1].page
})
setBottomSheetVisible(true)
}, [])
const children = useMemo(
() => (
<Icon
name='MoreHorizontal'
color={theme.secondary}
size={StyleConstants.Font.Size.L}
/>
),
[]
)
return (
<>
<Pressable style={styles.base} onPress={onPress} children={children} />
{modalVisible && (
<BottomSheet
visible={modalVisible}
handleDismiss={() => setBottomSheetVisible(false)}
>
{!sameAccount && (
<HeaderActionsAccount
queryKey={queryKey}
account={status.account}
setBottomSheetVisible={setBottomSheetVisible}
/>
)}
{sameAccount && (
<HeaderActionsStatus
queryKey={queryKey}
status={status}
setBottomSheetVisible={setBottomSheetVisible}
/>
)}
{!sameDomain && (
<HeaderActionsDomain
queryKey={queryKey}
domain={statusDomain}
setBottomSheetVisible={setBottomSheetVisible}
/>
)}
{url && type ? (
<HeaderActionsShare
url={url}
type={type}
setBottomSheetVisible={setBottomSheetVisible}
/>
) : null}
</BottomSheet>
)}
</>
)
},
() => true
)
const styles = StyleSheet.create({
base: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: StyleConstants.Spacing.S
}
})
export default HeaderActions

View File

@ -1,49 +0,0 @@
import analytics from '@components/analytics'
import MenuContainer from '@components/Menu/Container'
import MenuHeader from '@components/Menu/Header'
import MenuRow from '@components/Menu/Row'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Platform, Share } from 'react-native'
export interface Props {
type: 'status' | 'account'
url: string
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
}
const HeaderActionsShare: React.FC<Props> = ({
type,
url,
setBottomSheetVisible
}) => {
const { t } = useTranslation('componentTimeline')
return (
<MenuContainer>
<MenuHeader heading={t(`shared.header.actions.share.${type}.heading`)} />
<MenuRow
iconFront='Share2'
title={t(`shared.header.actions.share.${type}.button`)}
onPress={async () => {
analytics('timeline_shared_headeractions_share_press')
switch (Platform.OS) {
case 'ios':
await Share.share({
url
})
break
case 'android':
await Share.share({
message: url
})
break
}
setBottomSheetVisible(false)
}}
/>
</MenuContainer>
)
}
export default HeaderActionsShare

View File

@ -1,180 +0,0 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
import { useQueryClient } from 'react-query'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { toast } from '@components/toast'
import { useNavigation } from '@react-navigation/native'
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import analytics from '@components/analytics'
export interface Props {
queryKey: QueryKeyTimeline
status: Mastodon.Status
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
}
const HeaderActionsStatus: React.FC<Props> = ({
queryKey,
status,
setBottomSheetVisible
}) => {
const navigation = useNavigation()
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
const mutation = useTimelineMutation({
queryClient,
onMutate: true,
onError: (err: any, params, oldData) => {
const theFunction = (params as MutationVarsTimelineUpdateStatusProperty)
.payload
? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
: 'delete'
toast({
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(`shared.header.actions.status.${theFunction}.function`)
}),
...(err.status &&
typeof err.status === 'number' &&
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
})
queryClient.setQueryData(queryKey, oldData)
}
})
return (
<MenuContainer>
<MenuHeader heading={t('shared.header.actions.status.heading')} />
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
queryKey,
id: status.id
})
}}
iconFront='Trash'
title={t('shared.header.actions.status.delete.button')}
/>
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_status_deleteedit_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(
t('shared.header.actions.status.edit.alert.title'),
t('shared.header.actions.status.edit.alert.message'),
[
{
text: t(
'shared.header.actions.status.edit.alert.buttons.cancel'
),
style: 'cancel'
},
{
text: t(
'shared.header.actions.status.edit.alert.buttons.confirm'
),
style: 'destructive',
onPress: async () => {
analytics(
'timeline_shared_headeractions_status_deleteedit_confirm',
{
page: queryKey && queryKey[1].page
}
)
setBottomSheetVisible(false)
const res = await mutation.mutateAsync({
type: 'deleteItem',
source: 'statuses',
queryKey,
id: status.id
})
if (res.id) {
navigation.navigate('Screen-Compose', {
type: 'edit',
incomingStatus: res,
queryKey
})
}
}
}
]
)
}}
iconFront='Edit'
title={t('shared.header.actions.status.edit.button')}
/>
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_status_mute_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
id: status.id,
payload: {
property: 'muted',
currentValue: status.muted,
propertyCount: undefined,
countValue: undefined
}
})
}}
iconFront='VolumeX'
title={
status.muted
? t('shared.header.actions.status.mute.button.negative')
: t('shared.header.actions.status.mute.button.positive')
}
/>
{/* Also note that reblogs cannot be pinned. */}
{(status.visibility === 'public' || status.visibility === 'unlisted') && (
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_status_pin_press', {
page: queryKey && queryKey[1].page
})
setBottomSheetVisible(false)
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
id: status.id,
payload: {
property: 'pinned',
currentValue: status.pinned,
propertyCount: undefined,
countValue: undefined
}
})
}}
iconFront='Anchor'
title={
status.pinned
? t('shared.header.actions.status.pin.button.negative')
: t('shared.header.actions.status.pin.button.positive')
}
/>
)}
</MenuContainer>
)
}
export default HeaderActionsStatus

View File

@ -1,15 +1,19 @@
import { RelationshipOutgoing } from '@components/Relationship'
import Icon from '@components/Icon'
import {
RelationshipIncoming,
RelationshipOutgoing
} from '@components/Relationship'
import { useNavigation } from '@react-navigation/native'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { StyleSheet, View } from 'react-native'
import { Pressable, StyleSheet, View } from 'react-native'
import HeaderSharedAccount from './HeaderShared/Account'
import HeaderSharedApplication from './HeaderShared/Application'
import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedVisibility from './HeaderShared/Visibility'
import RelationshipIncoming from '@root/components/Relationship/Incoming'
import HeaderSharedMuted from './HeaderShared/Muted'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import ScreenActions from '@screens/Actions'
import HeaderSharedVisibility from './HeaderShared/Visibility'
export interface Props {
queryKey: QueryKeyTimeline
@ -20,6 +24,9 @@ const TimelineHeaderNotification: React.FC<Props> = ({
queryKey,
notification
}) => {
const navigation = useNavigation()
const { theme } = useTheme()
const actions = useMemo(() => {
switch (notification.type) {
case 'follow':
@ -27,11 +34,36 @@ const TimelineHeaderNotification: React.FC<Props> = ({
case 'follow_request':
return <RelationshipIncoming id={notification.account.id} />
default:
return notification.status ? (
<ScreenActions queryKey={queryKey} status={notification.status} />
) : null
if (notification.status) {
return (
<Pressable
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: StyleConstants.Spacing.S
}}
onPress={() =>
navigation.navigate('Screen-Actions', {
queryKey,
status,
url: notification.status?.url || notification.status?.uri,
type: 'status'
})
}
children={
<Icon
name='MoreHorizontal'
color={theme.secondary}
size={StyleConstants.Font.Size.L}
/>
}
/>
)
}
}
}, [notification.type])
return (
<View style={styles.base}>
<View

View File

@ -122,7 +122,7 @@ const ScreenActions = React.memo(
/>
)}
{sameAccount && (
{sameAccount && status && (
<ActionsStatus
navigation={navigation}
queryKey={queryKey}