Compare commits
221 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1b6f9c51c | |||
| 0d8a7cd816 | |||
| c9c4a107f2 | |||
| 43bc272615 | |||
| d563beb239 | |||
| 94771b5c7f | |||
| a941cc7758 | |||
| 759f022351 | |||
| 59b096196c | |||
| f39a27ed66 | |||
| d0bca3c576 | |||
| 03b44c0e45 | |||
| 10c9b26475 | |||
| 3e6a6960d4 | |||
| 5635bde707 | |||
| 1a8c6ac71e | |||
| 3bb220f8be | |||
| 8187a07aee | |||
| d054a69bcf | |||
| 4b1fe49132 | |||
| b2c139dbc0 | |||
| 02488f06d8 | |||
| b0d367a3b8 | |||
| 19c9ffa352 | |||
| cfc7d17db3 | |||
| 71b24952c7 | |||
| d7aed0b199 | |||
| 2823524388 | |||
| fd8083350c | |||
| 1411f33393 | |||
| 8840293c92 | |||
| 83fa99a4fe | |||
| 64473f5c98 | |||
| a45424fdb1 | |||
| 14d3389a63 | |||
| 311c7b52c8 | |||
| a8fd747187 | |||
| 259610ab37 | |||
| 44b4ec22d7 | |||
| f3dd6a89a1 | |||
| a60473b93f | |||
| c8c5ab05cd | |||
| 38219721c9 | |||
| 9d6e23b6e7 | |||
| ce69d13ec4 | |||
| 4875c2edaf | |||
| e39759a9a4 | |||
| 547b663bb6 | |||
| 6ab5776f95 | |||
| 9b40d4c8cc | |||
| a0a81da164 | |||
| 0220adaefb | |||
| 481dee52b1 | |||
| 78d74a3d7c | |||
| 83ca9059fa | |||
| 8da491cc3b | |||
| 8d1b3adb6a | |||
| 626f85651f | |||
| 2acc7ed107 | |||
| 14a2be33af | |||
| a642a3fe8f | |||
| b90f7eaefb | |||
| 455515cae1 | |||
| e3fc3b997a | |||
| 3c529e743f | |||
| 9d7f968cdd | |||
| b5769f9aed | |||
| ac98b322ca | |||
| c499f5f96a | |||
| d719b502d3 | |||
| 02e24c23a6 | |||
| c57ae4cea4 | |||
| 2536d6bf10 | |||
| 060ce2c725 | |||
| a8d2935cf2 | |||
| d6fb1528a0 | |||
| 2e3d170d1e | |||
| 4690e28cde | |||
| 66a754ad22 | |||
| 83a74f0f6e | |||
| 811b8cfc4c | |||
| a81d9cfca6 | |||
| c7ef5cd741 | |||
| 41f6afc528 | |||
| 37cb821d6b | |||
| 203bfc4c7c | |||
| 779556f36d | |||
| cf575cca68 | |||
| 97e6bdbe40 | |||
| 5f0101a360 | |||
| a3bb305229 | |||
| 808b33e7a7 | |||
| ac917ba829 | |||
| 6c3f2d3505 | |||
| 742a43658f | |||
| 0307e2e932 | |||
| 7c1add25a1 | |||
| feeab9205b | |||
| 1023653d97 | |||
| 077f2fe093 | |||
| d636ec6339 | |||
| 98c9a6ad32 | |||
| 33a4d2cbe5 | |||
| 8a5bc60819 | |||
| f492fd4d41 | |||
| ed7204ab71 | |||
| 9aeaa38f3b | |||
| b3f9ed7981 | |||
| b8ab064fcc | |||
| 58bf9cb8cd | |||
| 8a67e8d102 | |||
| 5d6fc56349 | |||
| 77ed2129d3 | |||
| fcebe8e0b0 | |||
| 6df617003a | |||
| 6953bf9d22 | |||
| 9396595595 | |||
| cf13b5cd4c | |||
| e24ab48b73 | |||
| bbee08eb22 | |||
| c68f291128 | |||
| 32b3575074 | |||
| 11f972c640 | |||
| 61cf754fd5 | |||
| 00b50c71b5 | |||
| 66eb6f2888 | |||
| bc571ee998 | |||
| c758996034 | |||
| 1f26494c94 | |||
| 74bfc10e36 | |||
| e194e5de91 | |||
| 09f96da982 | |||
| 6e48d63dda | |||
| eec636897c | |||
| 777f30562b | |||
| 16e4bc66bd | |||
| 98c5312a29 | |||
| 9971f1f035 | |||
| dec9d97171 | |||
| 355749e605 | |||
| 6268736bfa | |||
| a270d750c8 | |||
| 0eb4c7495e | |||
| b438318b92 | |||
| 01aaa6123f | |||
| 486a1f082c | |||
| f943cbd04a | |||
| c54fa5b2e4 | |||
| 54c0115181 | |||
| bb3a2fddfc | |||
| 5135a13812 | |||
| 059c3b362d | |||
| 090ceb4c53 | |||
| 7796203c25 | |||
| 44ae514d89 | |||
| 12d8e06a1e | |||
| de65d9198a | |||
| 41bf8e15cd | |||
| adeb1d5cec | |||
| 61511d5161 | |||
| aee205b0ab | |||
| e59763b50a | |||
| 5168d44926 | |||
| def3156c33 | |||
| a290891f70 | |||
| a96562e89c | |||
| 279d41fcd1 | |||
| 4932505c5e | |||
| 629b7d8c9b | |||
| 5c71f8e32a | |||
| 395a8838be | |||
| 17903b817d | |||
| 54f05bfcf6 | |||
| b1a058d098 | |||
| 27657541f2 | |||
| 73ea67f5c0 | |||
| d065b62f52 | |||
| eb03170736 | |||
| 6f734f7978 | |||
| 9235d6c13b | |||
| bc54c8d7c6 | |||
| 3b8dbbff12 | |||
| e8bb545023 | |||
| f0b30e26d4 | |||
| cbfa9f62a4 | |||
| fefd8cc8a0 | |||
| 09765a5d36 | |||
| e325b72c62 | |||
| 055a4d8e98 | |||
| 1e28ae6d2a | |||
| 16343a2936 | |||
| 18cc2183cc | |||
| 5e711c799b | |||
| ca4b9d3a60 | |||
| ebd03ffe2a | |||
| ee4f0673f1 | |||
| 33145f2e71 | |||
| 721fd84a7e | |||
| a06fd7dfd4 | |||
| bd6bb4df06 | |||
| bb4dc3c3a5 | |||
| 7b7fe7ccd8 | |||
| 316679ae68 | |||
| b34cae6db4 | |||
| 52e31394ab | |||
| 84f18e03fa | |||
| 30761594ec | |||
| 87258a2439 | |||
| 6e31e928a9 | |||
| d0587c81f8 | |||
| 29018f06b9 | |||
| 171cb6b3d3 | |||
| 3e37c27310 | |||
| 06c3ebe2d4 | |||
| d336cd58b1 | |||
| 684f67a8e0 | |||
| a7b23613d3 | |||
| a6db1a9ee3 | |||
| 0f065b2c27 | |||
| 7399e37bba | |||
| 7ce4c821e5 |
@@ -2,14 +2,18 @@ module.exports = {
|
||||
root: true,
|
||||
extends: '@react-native-community',
|
||||
parser: '@typescript-eslint/parser',
|
||||
// plugins: ['@typescript-eslint'],
|
||||
plugins: ['@typescript-eslint'],
|
||||
ignorePatterns: [
|
||||
'**/__mocks__/*.ts',
|
||||
'src/third-party',
|
||||
'ios',
|
||||
'android',
|
||||
'coverage',
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.js', '*.mjs', '*.ts', '*.tsx'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-undef': 'off',
|
||||
semi: [2, 'never'],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
linting:
|
||||
name: Run linters
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Yarn install
|
||||
run: yarn
|
||||
- name: Lint Reporter
|
||||
uses: wearerequired/lint-action@v2.2.0
|
||||
with:
|
||||
eslint: true
|
||||
prettier: true
|
||||
- name: Typescript & Lint check
|
||||
run: yarn lint
|
||||
testing:
|
||||
name: Run tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install node 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Yarn install
|
||||
run: yarn
|
||||
- name: Run tests
|
||||
run: |
|
||||
yarn test --forceExit
|
||||
@@ -59,3 +59,7 @@ buck-out/
|
||||
# Ruby / CocoaPods
|
||||
/ios/Pods/
|
||||
/vendor/bundle/
|
||||
|
||||
# Testing
|
||||
coverage/
|
||||
junit.xml
|
||||
@@ -0,0 +1,5 @@
|
||||
ios
|
||||
android
|
||||
src/third-party
|
||||
src/app.json
|
||||
public
|
||||
@@ -1 +1 @@
|
||||
2.7.4
|
||||
2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||
ruby '2.7.4'
|
||||
ruby File.read(File.join(__dir__, '.ruby-version')).strip
|
||||
|
||||
gem 'cocoapods', '~> 1.11', '>= 1.11.2'
|
||||
gem 'cocoapods', '~> 1.11', '>= 1.11.3'
|
||||
@@ -16,8 +16,10 @@ Uses:
|
||||
- After initial setup:
|
||||
- `cd ios ; pod install`
|
||||
- Start the dev servers
|
||||
- `yarn dev-pds`
|
||||
- `yarn dev-wallet`
|
||||
- `git clone git@github.com:bluesky-social/atproto.git`
|
||||
- `cd atproto`
|
||||
- `yarn`
|
||||
- `cd packages/dev-env && yarn start`
|
||||
- Run the dev app
|
||||
- iOS: `yarn ios`
|
||||
- Android: `yarn android`
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from 'react'
|
||||
import {View, ScrollView, Modal, FlatList, TextInput} from 'react-native'
|
||||
|
||||
const BottomSheetModalContext = React.createContext(null)
|
||||
|
||||
const BottomSheetModalProvider = (props: any) => {
|
||||
return <BottomSheetModalContext.Provider {...props} value={{}} />
|
||||
}
|
||||
class BottomSheet extends React.Component {
|
||||
snapToIndex() {}
|
||||
snapToPosition() {}
|
||||
expand() {}
|
||||
collapse() {}
|
||||
close() {
|
||||
this.props.onClose?.()
|
||||
}
|
||||
forceClose() {}
|
||||
|
||||
render() {
|
||||
return <View>{this.props.children}</View>
|
||||
}
|
||||
}
|
||||
const BottomSheetModal = (props: any) => <Modal {...props} />
|
||||
|
||||
const BottomSheetBackdrop = (props: any) => <View {...props} />
|
||||
const BottomSheetHandle = (props: any) => <View {...props} />
|
||||
const BottomSheetFooter = (props: any) => <View {...props} />
|
||||
const BottomSheetScrollView = (props: any) => <ScrollView {...props} />
|
||||
const BottomSheetFlatList = (props: any) => <FlatList {...props} />
|
||||
const BottomSheetTextInput = (props: any) => <TextInput {...props} />
|
||||
|
||||
const useBottomSheet = jest.fn()
|
||||
const useBottomSheetModal = jest.fn()
|
||||
const useBottomSheetSpringConfigs = jest.fn()
|
||||
const useBottomSheetTimingConfigs = jest.fn()
|
||||
const useBottomSheetInternal = jest.fn()
|
||||
const useBottomSheetDynamicSnapPoints = jest.fn()
|
||||
|
||||
export {useBottomSheet}
|
||||
export {useBottomSheetModal}
|
||||
export {useBottomSheetSpringConfigs}
|
||||
export {useBottomSheetTimingConfigs}
|
||||
export {useBottomSheetInternal}
|
||||
export {useBottomSheetDynamicSnapPoints}
|
||||
|
||||
export {
|
||||
BottomSheetModalProvider,
|
||||
BottomSheetBackdrop,
|
||||
BottomSheetHandle,
|
||||
BottomSheetModal,
|
||||
BottomSheetFooter,
|
||||
BottomSheetScrollView,
|
||||
BottomSheetFlatList,
|
||||
BottomSheetTextInput,
|
||||
}
|
||||
|
||||
export default BottomSheet
|
||||
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
requestPermission: jest.fn(),
|
||||
onForegroundEvent: jest.fn(),
|
||||
setBadgeCount: jest.fn(),
|
||||
displayNotification: jest.fn(),
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export const CameraRoll = {
|
||||
getPhotos: jest.fn().mockResolvedValue({
|
||||
edges: [
|
||||
{node: {image: {uri: 'path/to/image1.jpg'}}},
|
||||
{node: {image: {uri: 'path/to/image2.jpg'}}},
|
||||
{node: {image: {uri: 'path/to/image3.jpg'}}},
|
||||
],
|
||||
}),
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export default from '@react-native-async-storage/async-storage/jest/async-storage-mock'
|
||||
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
configure: jest.fn().mockResolvedValue(0),
|
||||
finish: jest.fn(),
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export default {}
|
||||
@@ -0,0 +1,9 @@
|
||||
export const openPicker = jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({uri: ''}))
|
||||
export const openCamera = jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({uri: ''}))
|
||||
export const openCropper = jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({uri: ''}))
|
||||
@@ -0,0 +1,10 @@
|
||||
jest.mock('rn-fetch-blob', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: {
|
||||
fs: {
|
||||
unlink: jest.fn(),
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,937 @@
|
||||
import {LogModel} from './../src/state/models/log'
|
||||
import {LRUMap} from 'lru_map'
|
||||
import {RootStoreModel} from './../src/state/models/root-store'
|
||||
import {NavigationTabModel} from './../src/state/models/navigation'
|
||||
import {SessionModel} from '../src/state/models/session'
|
||||
import {NavigationModel} from '../src/state/models/navigation'
|
||||
import {ShellUiModel} from '../src/state/models/shell-ui'
|
||||
import {MeModel} from '../src/state/models/me'
|
||||
import {OnboardModel} from '../src/state/models/onboard'
|
||||
import {ProfilesViewModel} from '../src/state/models/profiles-view'
|
||||
import {LinkMetasViewModel} from '../src/state/models/link-metas-view'
|
||||
import {MembershipsViewModel} from '../src/state/models/memberships-view'
|
||||
import {FeedModel} from '../src/state/models/feed-view'
|
||||
import {NotificationsViewModel} from '../src/state/models/notifications-view'
|
||||
import {ProfileViewModel} from '../src/state/models/profile-view'
|
||||
import {MembersViewModel} from '../src/state/models/members-view'
|
||||
import {ProfileUiModel, Sections} from '../src/state/models/profile-ui'
|
||||
import {SessionServiceClient} from '@atproto/api'
|
||||
import {UserAutocompleteViewModel} from '../src/state/models/user-autocomplete-view'
|
||||
import {UserLocalPhotosModel} from '../src/state/models/user-local-photos'
|
||||
import {SuggestedActorsViewModel} from '../src/state/models/suggested-actors-view'
|
||||
import {UserFollowersViewModel} from '../src/state/models/user-followers-view'
|
||||
import {UserFollowsViewModel} from '../src/state/models/user-follows-view'
|
||||
import {NotificationsViewItemModel} from './../src/state/models/notifications-view'
|
||||
import {
|
||||
PostThreadViewModel,
|
||||
PostThreadViewPostModel,
|
||||
} from '../src/state/models/post-thread-view'
|
||||
import {FeedItemModel} from '../src/state/models/feed-view'
|
||||
import {RepostedByViewModel} from '../src/state/models/reposted-by-view'
|
||||
import {VotesViewModel} from '../src/state/models/votes-view'
|
||||
|
||||
export const mockedProfileStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: true,
|
||||
error: '',
|
||||
params: {
|
||||
actor: '',
|
||||
},
|
||||
did: 'test did',
|
||||
handle: 'testhandle',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: '',
|
||||
},
|
||||
creator: 'test did',
|
||||
displayName: '',
|
||||
description: '',
|
||||
avatar: '',
|
||||
banner: '',
|
||||
followersCount: 0,
|
||||
followsCount: 0,
|
||||
membersCount: 0,
|
||||
postsCount: 0,
|
||||
myState: {
|
||||
follow: '',
|
||||
member: '',
|
||||
},
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
isUser: true,
|
||||
isScene: false,
|
||||
setup: jest.fn().mockResolvedValue({aborted: false}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
toggleFollowing: jest.fn().mockResolvedValue({}),
|
||||
updateProfile: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _load, _replaceAll
|
||||
} as unknown as ProfileViewModel
|
||||
|
||||
export const mockedMembersStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: true,
|
||||
error: '',
|
||||
params: {
|
||||
actor: 'test actor',
|
||||
},
|
||||
subject: {
|
||||
did: 'test did',
|
||||
handle: '',
|
||||
displayName: '',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: '',
|
||||
},
|
||||
avatar: undefined,
|
||||
},
|
||||
members: [
|
||||
{
|
||||
did: 'test did2',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: '',
|
||||
},
|
||||
handle: 'testhandle',
|
||||
displayName: 'test name',
|
||||
indexedAt: '',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
isMember: jest.fn(),
|
||||
setup: jest.fn().mockResolvedValue({aborted: false}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn(),
|
||||
removeMember: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _fetch, _replaceAll, _append
|
||||
} as unknown as MembersViewModel
|
||||
|
||||
export const mockedMembershipsStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: true,
|
||||
error: '',
|
||||
params: {
|
||||
actor: '',
|
||||
limit: 1,
|
||||
before: '',
|
||||
},
|
||||
subject: {
|
||||
did: 'test did',
|
||||
handle: '',
|
||||
displayName: '',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
avatar: undefined,
|
||||
},
|
||||
memberships: [
|
||||
{
|
||||
did: 'test did',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: 'app.bsky.system.actorUser',
|
||||
},
|
||||
handle: ',',
|
||||
displayName: '',
|
||||
createdAt: '',
|
||||
indexedAt: '',
|
||||
_reactKey: 'item-1',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
isMemberOf: jest.fn(),
|
||||
setup: jest.fn().mockResolvedValue({aborted: false}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _fetch, _replaceAll, _append
|
||||
} as unknown as MembershipsViewModel
|
||||
|
||||
export const mockedFeedItemStore = {
|
||||
_reactKey: 'item-1',
|
||||
_isThreadParent: false,
|
||||
_isThreadChildElided: false,
|
||||
_isThreadChild: false,
|
||||
post: {
|
||||
uri: 'testuri',
|
||||
cid: 'test cid',
|
||||
author: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
displayName: 'test name',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
createdAt: '2022-12-29T16:39:57.919Z',
|
||||
text: 'Sup',
|
||||
},
|
||||
replyCount: 0,
|
||||
repostCount: 0,
|
||||
upvoteCount: 0,
|
||||
downvoteCount: 0,
|
||||
indexedAt: '2022-12-29T16:39:57.919Z',
|
||||
viewer: {},
|
||||
},
|
||||
postRecord: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
text: 'test text',
|
||||
createdAt: '1',
|
||||
reply: {
|
||||
root: {
|
||||
uri: 'testuri',
|
||||
cid: 'tes cid',
|
||||
},
|
||||
parent: {
|
||||
uri: 'testuri',
|
||||
cid: 'tes cid',
|
||||
},
|
||||
},
|
||||
},
|
||||
rootStore: {} as RootStoreModel,
|
||||
copy: jest.fn(),
|
||||
toggleUpvote: jest.fn().mockResolvedValue({}),
|
||||
toggleDownvote: jest.fn(),
|
||||
toggleRepost: jest.fn().mockResolvedValue({}),
|
||||
delete: jest.fn().mockResolvedValue({}),
|
||||
reasonRepost: {
|
||||
by: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
indexedAt: '',
|
||||
},
|
||||
reasonTrend: {
|
||||
by: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
indexedAt: '',
|
||||
},
|
||||
reply: {
|
||||
parent: {
|
||||
author: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
displayName: 'test name',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
cid: '',
|
||||
downvoteCount: 0,
|
||||
indexedAt: '2023-01-10T11:17:46.945Z',
|
||||
record: {},
|
||||
replyCount: 1,
|
||||
repostCount: 0,
|
||||
upvoteCount: 0,
|
||||
uri: 'testuri',
|
||||
viewer: {},
|
||||
},
|
||||
root: {
|
||||
author: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
displayName: 'test name',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
cid: '',
|
||||
downvoteCount: 0,
|
||||
indexedAt: '2023-01-10T11:17:46.739Z',
|
||||
record: {},
|
||||
replyCount: 1,
|
||||
repostCount: 0,
|
||||
upvoteCount: 1,
|
||||
uri: 'testuri',
|
||||
viewer: {},
|
||||
},
|
||||
},
|
||||
} as FeedItemModel
|
||||
|
||||
export const mockedFeedStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasNewLatest: false,
|
||||
hasLoaded: true,
|
||||
error: '',
|
||||
hasMore: true,
|
||||
params: {
|
||||
actor: '',
|
||||
limit: 1,
|
||||
before: '',
|
||||
},
|
||||
feed: [],
|
||||
rootStore: {} as RootStoreModel,
|
||||
feedType: 'home',
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
nonReplyFeed: [
|
||||
{
|
||||
_reactKey: 'item-1',
|
||||
post: {
|
||||
author: {
|
||||
handle: 'handle.test',
|
||||
displayName: 'test name',
|
||||
avatar: '',
|
||||
},
|
||||
cid: 'bafyreihkwjoy2vbfqld2lp3tv4ce6yfr354sqgp32qoplrudso4gyyjiwe',
|
||||
downvoteCount: 0,
|
||||
indexedAt: '2022-12-29T16:35:55.270Z',
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
createdAt: '2022-12-29T16:39:57.919Z',
|
||||
text: 'Sup',
|
||||
},
|
||||
replyCount: 0,
|
||||
repostCount: 0,
|
||||
upvoteCount: 0,
|
||||
uri: 'at://did:plc:wcizmlgv3rdslk64t6q4silu/app.bsky.feed.post/3jkzce5kfvn2h',
|
||||
viewer: {
|
||||
handle: 'handle.test',
|
||||
displayName: 'test name',
|
||||
avatar: '',
|
||||
},
|
||||
},
|
||||
reason: undefined,
|
||||
reply: undefined,
|
||||
},
|
||||
],
|
||||
setHasNewLatest: jest.fn(),
|
||||
setup: jest.fn().mockResolvedValue({}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn().mockResolvedValue({}),
|
||||
loadLatest: jest.fn(),
|
||||
update: jest.fn(),
|
||||
checkForLatest: jest.fn().mockRejectedValue('Error checking for latest'),
|
||||
registerListeners: jest.fn().mockReturnValue(jest.fn()),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _pendingWork, _initialLoad, _loadLatest, _loadMore, _update, _replaceAll, _appendAll, _prependAll, _updateAll, _getFeed, loadMoreCursor, pollCursor, _loadPromise, _updatePromise, _loadLatestPromise, _loadMorePromise
|
||||
} as unknown as FeedModel
|
||||
|
||||
export const mockedPostThreadViewPostStore = {
|
||||
_reactKey: 'item-1',
|
||||
_depth: 0,
|
||||
_isHighlightedPost: false,
|
||||
_hasMore: false,
|
||||
postRecord: {
|
||||
text: 'test text',
|
||||
createdAt: '',
|
||||
reply: {
|
||||
root: {
|
||||
uri: 'testuri',
|
||||
cid: 'tes cid',
|
||||
},
|
||||
parent: {
|
||||
uri: 'testuri',
|
||||
cid: 'tes cid',
|
||||
},
|
||||
},
|
||||
},
|
||||
post: {
|
||||
uri: 'testuri',
|
||||
cid: 'testcid',
|
||||
record: {},
|
||||
author: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
viewer: {
|
||||
muted: true,
|
||||
},
|
||||
},
|
||||
replyCount: 0,
|
||||
repostCount: 0,
|
||||
upvoteCount: 0,
|
||||
downvoteCount: 0,
|
||||
indexedAt: '',
|
||||
viewer: {
|
||||
repost: '',
|
||||
upvote: '',
|
||||
downvote: '',
|
||||
},
|
||||
},
|
||||
rootStore: {} as RootStoreModel,
|
||||
assignTreeModels: jest.fn(),
|
||||
toggleRepost: jest.fn().mockRejectedValue({}),
|
||||
toggleUpvote: jest.fn().mockRejectedValue({}),
|
||||
toggleDownvote: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
} as PostThreadViewPostModel
|
||||
|
||||
export const mockedPostThreadViewStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
notFound: false,
|
||||
resolvedUri: 'testuri',
|
||||
params: {
|
||||
uri: 'testuri',
|
||||
},
|
||||
thread: mockedPostThreadViewPostStore,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
setup: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
update: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _resolveUri, _load, _replaceAll
|
||||
} as unknown as PostThreadViewModel
|
||||
|
||||
export const mockedNotificationsViewItemStore = {
|
||||
_reactKey: 'item-1',
|
||||
uri: 'testuri',
|
||||
cid: '',
|
||||
author: {
|
||||
did: 'test did',
|
||||
handle: 'test.handle',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
rootStore: {} as RootStoreModel,
|
||||
copy: jest.fn(),
|
||||
reason: 'test reason',
|
||||
isRead: true,
|
||||
indexedAt: '',
|
||||
isUpvote: true,
|
||||
isRepost: false,
|
||||
isTrend: false,
|
||||
isMention: false,
|
||||
isReply: false,
|
||||
isFollow: false,
|
||||
isAssertion: false,
|
||||
needsAdditionalData: false,
|
||||
isInvite: false,
|
||||
subjectUri: 'testuri',
|
||||
toSupportedRecord: jest.fn().mockReturnValue({
|
||||
text: 'test text',
|
||||
createdAt: '',
|
||||
}),
|
||||
fetchAdditionalData: jest.fn(),
|
||||
toNotifeeOpts: jest.fn(),
|
||||
} as NotificationsViewItemModel
|
||||
|
||||
export const mockedNotificationsStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: true,
|
||||
error: '',
|
||||
params: {
|
||||
limit: 1,
|
||||
before: '',
|
||||
},
|
||||
hasMore: true,
|
||||
notifications: [mockedNotificationsViewItemStore],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn().mockResolvedValue({aborted: false}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn().mockResolvedValue({}),
|
||||
update: jest.fn().mockResolvedValue(null),
|
||||
updateReadState: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _pendingWork, _initialLoad, _loadMore, _update, _replaceAll, _appendAll, _updateAll, loadMoreCursor, _loadPromise, _updatePromise, _loadLatestPromise, _loadMorePromise
|
||||
} as unknown as NotificationsViewModel
|
||||
|
||||
export const mockedSessionStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
data: {
|
||||
service: '',
|
||||
refreshJwt: '',
|
||||
accessJwt: '',
|
||||
handle: '',
|
||||
did: 'test did',
|
||||
},
|
||||
online: false,
|
||||
attemptingConnect: false,
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasSession: true,
|
||||
clear: jest.fn(),
|
||||
setState: jest.fn(),
|
||||
setOnline: jest.fn(),
|
||||
updateAuthTokens: jest.fn(),
|
||||
connect: jest.fn(),
|
||||
describeService: jest.fn().mockResolvedValue({
|
||||
availableUserDomains: ['test'],
|
||||
links: {
|
||||
termsOfService: 'https://testTermsOfService',
|
||||
privacyPolicy: 'https://testPrivacyPolicy',
|
||||
},
|
||||
}),
|
||||
login: jest.fn(),
|
||||
createAccount: jest.fn(),
|
||||
logout: jest.fn(),
|
||||
|
||||
// unknown required because of the missing private methods: _connectPromise, configureApi & _connect
|
||||
} as unknown as SessionModel
|
||||
|
||||
export const mockedNavigationTabStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
id: 0,
|
||||
history: [
|
||||
{
|
||||
url: '',
|
||||
ts: 0,
|
||||
title: '',
|
||||
id: 0,
|
||||
},
|
||||
],
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
current: {
|
||||
url: '',
|
||||
ts: 0,
|
||||
title: '',
|
||||
id: 0,
|
||||
},
|
||||
canGoBack: false,
|
||||
canGoForward: false,
|
||||
backTen: [
|
||||
{
|
||||
url: '',
|
||||
title: '',
|
||||
index: 0,
|
||||
id: 0,
|
||||
},
|
||||
],
|
||||
forwardTen: [
|
||||
{
|
||||
url: '',
|
||||
title: '',
|
||||
index: 0,
|
||||
id: 0,
|
||||
},
|
||||
],
|
||||
navigate: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
goBack: jest.fn(),
|
||||
fixedTabReset: jest.fn(),
|
||||
goForward: jest.fn(),
|
||||
goToIndex: jest.fn(),
|
||||
setTitle: jest.fn(),
|
||||
setIsNewTab: jest.fn(),
|
||||
fixedTabPurpose: 0,
|
||||
getBackList: () => [
|
||||
{
|
||||
url: '/',
|
||||
title: '',
|
||||
index: 1,
|
||||
id: 1,
|
||||
},
|
||||
],
|
||||
getForwardList: jest.fn(),
|
||||
} as NavigationTabModel
|
||||
|
||||
export const mockedNavigationStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
tabs: [mockedNavigationTabStore],
|
||||
tabIndex: 0,
|
||||
clear: jest.fn(),
|
||||
tab: mockedNavigationTabStore,
|
||||
tabCount: 1,
|
||||
isCurrentScreen: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
setTitle: jest.fn(),
|
||||
handleLink: jest.fn(),
|
||||
switchTo: jest.fn(),
|
||||
setActiveTab: jest.fn(),
|
||||
closeTab: jest.fn(),
|
||||
newTab: jest.fn(),
|
||||
} as NavigationModel
|
||||
|
||||
export const mockedShellStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
minimalShellMode: false,
|
||||
isMainMenuOpen: false,
|
||||
isModalActive: false,
|
||||
activeModal: undefined,
|
||||
isLightboxActive: false,
|
||||
activeLightbox: undefined,
|
||||
isComposerActive: false,
|
||||
composerOpts: undefined,
|
||||
darkMode: false,
|
||||
setDarkMode: jest.fn(),
|
||||
setMainMenuOpen: jest.fn(),
|
||||
setMinimalShellMode: jest.fn(),
|
||||
openModal: jest.fn(),
|
||||
closeModal: jest.fn(),
|
||||
closeComposer: jest.fn(),
|
||||
closeLightbox: jest.fn(),
|
||||
openComposer: jest.fn(),
|
||||
openLightbox: jest.fn(),
|
||||
} as ShellUiModel
|
||||
|
||||
export const mockedMeStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
did: 'test did',
|
||||
handle: 'test',
|
||||
displayName: 'test',
|
||||
description: 'test',
|
||||
avatar: '',
|
||||
notificationCount: 0,
|
||||
rootStore: {} as RootStoreModel,
|
||||
memberships: mockedMembershipsStore,
|
||||
mainFeed: mockedFeedStore,
|
||||
notifications: mockedNotificationsStore,
|
||||
clear: jest.fn(),
|
||||
load: jest.fn(),
|
||||
clearNotificationCount: jest.fn(),
|
||||
fetchNotifications: jest.fn(),
|
||||
refreshMemberships: jest.fn(),
|
||||
} as MeModel
|
||||
|
||||
export const mockedOnboardStore = {
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
isOnboarding: false,
|
||||
stage: '',
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
next: jest.fn(),
|
||||
} as OnboardModel
|
||||
|
||||
export const mockedProfilesStore = {
|
||||
hydrate: jest.fn(),
|
||||
serialize: jest.fn(),
|
||||
cache: new LRUMap(100),
|
||||
rootStore: {} as RootStoreModel,
|
||||
getProfile: jest.fn().mockResolvedValue({data: {}}),
|
||||
overwrite: jest.fn(),
|
||||
} as ProfilesViewModel
|
||||
|
||||
export const mockedLinkMetasStore = {
|
||||
hydrate: jest.fn(),
|
||||
serialize: jest.fn(),
|
||||
cache: new LRUMap(100),
|
||||
rootStore: {} as RootStoreModel,
|
||||
getLinkMeta: jest.fn(),
|
||||
} as LinkMetasViewModel
|
||||
|
||||
export const mockedLogStore = {
|
||||
entries: [],
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
// unknown required because of the missing private methods: add
|
||||
} as unknown as LogModel
|
||||
|
||||
export const mockedRootStore = {
|
||||
api: {
|
||||
com: {},
|
||||
app: {
|
||||
bsky: {
|
||||
actor: {
|
||||
searchTypeahead: jest.fn().mockResolvedValue({data: {users: []}}),
|
||||
},
|
||||
graph: {
|
||||
getFollows: jest.fn().mockResolvedValue({data: {follows: []}}),
|
||||
getFollowers: jest.fn().mockResolvedValue({}),
|
||||
getMembers: jest.fn().mockResolvedValue({}),
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as SessionServiceClient,
|
||||
resolveName: jest.fn(),
|
||||
serialize: jest.fn(),
|
||||
hydrate: jest.fn(),
|
||||
fetchStateUpdate: jest.fn(),
|
||||
clearAll: jest.fn(),
|
||||
session: mockedSessionStore,
|
||||
nav: mockedNavigationStore,
|
||||
shell: mockedShellStore,
|
||||
me: mockedMeStore,
|
||||
onboard: mockedOnboardStore,
|
||||
profiles: mockedProfilesStore,
|
||||
linkMetas: mockedLinkMetasStore,
|
||||
log: mockedLogStore,
|
||||
} as RootStoreModel
|
||||
|
||||
export const mockedProfileUiStore = {
|
||||
profile: mockedProfileStore,
|
||||
feed: mockedFeedStore,
|
||||
memberships: mockedMembershipsStore,
|
||||
members: mockedMembersStore,
|
||||
selectedViewIndex: 0,
|
||||
rootStore: mockedRootStore,
|
||||
params: {
|
||||
user: 'test user',
|
||||
},
|
||||
currentView: mockedFeedStore,
|
||||
isInitialLoading: false,
|
||||
isRefreshing: false,
|
||||
isUser: true,
|
||||
isScene: false,
|
||||
selectorItems: [Sections.Posts, Sections.PostsWithReplies, Sections.Scenes],
|
||||
selectedView: Sections.Posts,
|
||||
setSelectedViewIndex: jest.fn(),
|
||||
setup: jest.fn().mockResolvedValue({aborted: false}),
|
||||
update: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn(),
|
||||
} as ProfileUiModel
|
||||
|
||||
export const mockedAutocompleteViewStore = {
|
||||
isLoading: false,
|
||||
isActive: true,
|
||||
prefix: '',
|
||||
follows: [
|
||||
{
|
||||
did: 'test did',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: 'app.bsky.system.actorUser',
|
||||
},
|
||||
handle: '',
|
||||
displayName: '',
|
||||
createdAt: '',
|
||||
indexedAt: '',
|
||||
},
|
||||
],
|
||||
searchRes: [
|
||||
{
|
||||
did: 'test did',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: 'app.bsky.system.actorUser',
|
||||
},
|
||||
handle: '',
|
||||
displayName: '',
|
||||
},
|
||||
],
|
||||
knownHandles: new Set<string>(),
|
||||
suggestions: [
|
||||
{
|
||||
handle: 'handle.test',
|
||||
displayName: 'Test Display',
|
||||
},
|
||||
{
|
||||
handle: 'handle2.test',
|
||||
displayName: 'Test Display 2',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
setup: jest.fn(),
|
||||
setActive: jest.fn(),
|
||||
setPrefix: jest.fn(),
|
||||
// unknown required because of the missing private methods: _searchPromise, _getFollows , _search
|
||||
} as unknown as UserAutocompleteViewModel
|
||||
|
||||
export const mockedLocalPhotosStore = {
|
||||
photos: {
|
||||
node: {
|
||||
type: '',
|
||||
group_name: '',
|
||||
image: {
|
||||
filename: '',
|
||||
extension: '',
|
||||
uri: '',
|
||||
height: 1000,
|
||||
width: 1000,
|
||||
fileSize: null,
|
||||
playableDuration: 0,
|
||||
},
|
||||
timestamp: 1672847197,
|
||||
location: null,
|
||||
},
|
||||
},
|
||||
rootStore: {} as RootStoreModel,
|
||||
setup: jest.fn(),
|
||||
// unknown required because of the missing private methods: _getPhotos
|
||||
} as unknown as UserLocalPhotosModel
|
||||
|
||||
export const mockedSuggestedActorsStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
suggestions: [
|
||||
{
|
||||
did: '1',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: 'app.bsky.system.actorUser',
|
||||
},
|
||||
handle: 'handle1.test',
|
||||
displayName: 'test name 1',
|
||||
description: 'desc',
|
||||
indexedAt: '',
|
||||
_reactKey: '1',
|
||||
},
|
||||
{
|
||||
did: '2',
|
||||
declaration: {
|
||||
cid: '',
|
||||
actorType: 'app.bsky.system.actorUser',
|
||||
},
|
||||
handle: '',
|
||||
displayName: 'handle2.test',
|
||||
description: 'desc',
|
||||
indexedAt: '',
|
||||
_reactKey: '2',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn().mockResolvedValue(null),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
// unknown required because of the missing private methods: _xLoading, _xIdle, _fetch, _appendAll, _append
|
||||
} as unknown as SuggestedActorsViewModel
|
||||
|
||||
export const mockedUserFollowersStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
params: {
|
||||
user: 'test user',
|
||||
},
|
||||
subject: {
|
||||
did: 'test did',
|
||||
handle: '',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
followers: [
|
||||
{
|
||||
did: 'test did',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
handle: 'testhandle',
|
||||
displayName: 'test name',
|
||||
indexedAt: '',
|
||||
_reactKey: '1',
|
||||
},
|
||||
{
|
||||
did: 'test did2',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
handle: 'testhandle2',
|
||||
displayName: 'test name 2',
|
||||
indexedAt: '',
|
||||
_reactKey: '2',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xIdle, _xLoading, _fetch, _replaceAll, _append
|
||||
} as unknown as UserFollowersViewModel
|
||||
|
||||
export const mockedUserFollowsStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
params: {
|
||||
user: 'test user',
|
||||
},
|
||||
subject: {
|
||||
did: 'test did',
|
||||
handle: '',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
follows: [
|
||||
{
|
||||
did: 'test did',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
handle: 'testhandle',
|
||||
displayName: 'test name',
|
||||
indexedAt: '',
|
||||
_reactKey: '1',
|
||||
},
|
||||
{
|
||||
did: 'test did2',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
handle: 'testhandle2',
|
||||
displayName: 'test name 2',
|
||||
indexedAt: '',
|
||||
_reactKey: '2',
|
||||
},
|
||||
],
|
||||
rootStore: {} as RootStoreModel,
|
||||
hasContent: true,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn(),
|
||||
// unknown required because of the missing private methods: _xIdle, _xLoading, _fetch, _replaceAll, _append
|
||||
} as unknown as UserFollowsViewModel
|
||||
|
||||
export const mockedRepostedByViewStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
resolvedUri: '',
|
||||
params: {
|
||||
uri: 'testuri',
|
||||
},
|
||||
uri: '',
|
||||
repostedBy: [
|
||||
{
|
||||
_reactKey: '',
|
||||
did: '',
|
||||
handle: '',
|
||||
displayName: '',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
indexedAt: '',
|
||||
},
|
||||
],
|
||||
hasContent: false,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn().mockResolvedValue({}),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn().mockResolvedValue({}),
|
||||
// unknown required because of the missing private methods: _xIdle, _xLoading, _resolveUri, _fetch, _refresh, _replaceAll, _append
|
||||
} as unknown as RepostedByViewModel
|
||||
|
||||
export const mockedVotesViewStore = {
|
||||
isLoading: false,
|
||||
isRefreshing: false,
|
||||
hasLoaded: false,
|
||||
error: '',
|
||||
resolvedUri: '',
|
||||
params: {
|
||||
uri: 'testuri',
|
||||
},
|
||||
uri: '',
|
||||
votes: [
|
||||
{
|
||||
_reactKey: '',
|
||||
direction: 'up',
|
||||
indexedAt: '',
|
||||
createdAt: '',
|
||||
actor: {
|
||||
did: '',
|
||||
handle: '',
|
||||
declaration: {cid: '', actorType: ''},
|
||||
},
|
||||
},
|
||||
],
|
||||
hasContent: false,
|
||||
hasError: false,
|
||||
isEmpty: false,
|
||||
setup: jest.fn(),
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
loadMore: jest.fn().mockResolvedValue({}),
|
||||
// unknown required because of the missing private methods: _xIdle, _xLoading, _resolveUri, _fetch, _replaceAll, _append
|
||||
} as unknown as VotesViewModel
|
||||
@@ -1,16 +0,0 @@
|
||||
// /**
|
||||
// * @format
|
||||
// */
|
||||
|
||||
// import 'react-native'
|
||||
// import React from 'react'
|
||||
// import App from '../src/App'
|
||||
|
||||
// // Note: test renderer must be required after react-native.
|
||||
// import renderer from 'react-test-renderer'
|
||||
|
||||
// it('renders correctly', () => {
|
||||
// renderer.act(() => {
|
||||
// renderer.create(<App />)
|
||||
// })
|
||||
// })
|
||||
@@ -0,0 +1,257 @@
|
||||
import React from 'react'
|
||||
import {MobileShell} from '../src/view/shell/mobile'
|
||||
import {cleanup, fireEvent, render, waitFor} from '../jest/test-utils'
|
||||
import {createServer, TestPDS} from '../jest/test-pds'
|
||||
import {RootStoreModel, setupState} from '../src/state'
|
||||
|
||||
const WAIT_OPTS = {timeout: 5e3}
|
||||
|
||||
describe('Account flows', () => {
|
||||
let pds: TestPDS | undefined
|
||||
let rootStore: RootStoreModel | undefined
|
||||
beforeAll(async () => {
|
||||
jest.useFakeTimers()
|
||||
pds = await createServer()
|
||||
rootStore = await setupState(pds.pdsUrl)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
await pds?.close()
|
||||
})
|
||||
|
||||
it('renders initial screen', () => {
|
||||
const {getByTestId} = render(<MobileShell />, rootStore)
|
||||
const signUpScreen = getByTestId('signinOrCreateAccount')
|
||||
|
||||
expect(signUpScreen).toBeTruthy()
|
||||
})
|
||||
|
||||
it('completes signin to the server', async () => {
|
||||
const {getByTestId} = render(<MobileShell />, rootStore)
|
||||
|
||||
// move to signin view
|
||||
fireEvent.press(getByTestId('signInButton'))
|
||||
expect(getByTestId('signIn')).toBeTruthy()
|
||||
expect(getByTestId('loginForm')).toBeTruthy()
|
||||
|
||||
// input the target server
|
||||
expect(getByTestId('loginSelectServiceButton')).toBeTruthy()
|
||||
fireEvent.press(getByTestId('loginSelectServiceButton'))
|
||||
expect(getByTestId('serverInputModal')).toBeTruthy()
|
||||
fireEvent.changeText(
|
||||
getByTestId('customServerTextInput'),
|
||||
pds?.pdsUrl || '',
|
||||
)
|
||||
fireEvent.press(getByTestId('customServerSelectBtn'))
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('loginUsernameInput')).toBeTruthy()
|
||||
}, WAIT_OPTS)
|
||||
|
||||
// enter username & pass
|
||||
fireEvent.changeText(getByTestId('loginUsernameInput'), 'alice')
|
||||
fireEvent.changeText(getByTestId('loginPasswordInput'), 'hunter2')
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('loginNextButton')).toBeTruthy()
|
||||
}, WAIT_OPTS)
|
||||
fireEvent.press(getByTestId('loginNextButton'))
|
||||
|
||||
// signed in
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('homeFeed')).toBeTruthy()
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(1)
|
||||
}, WAIT_OPTS)
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(1)
|
||||
})
|
||||
|
||||
it('opens the login screen when "add account" is pressed', async () => {
|
||||
const {getByTestId, getAllByTestId} = render(<MobileShell />, rootStore)
|
||||
await waitFor(() => expect(getByTestId('homeFeed')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// open side menu
|
||||
fireEvent.press(getAllByTestId('viewHeaderBackOrMenuBtn')[0])
|
||||
await waitFor(() => expect(getByTestId('menuView')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// nav to settings
|
||||
fireEvent.press(getByTestId('menuItemButton-Settings'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('settingsScreen')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// press '+ new account' in switcher
|
||||
fireEvent.press(getByTestId('switchToNewAccountBtn'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('signinOrCreateAccount')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
})
|
||||
|
||||
it('shows the "choose account" form when a previous session has been created', async () => {
|
||||
const {getByTestId} = render(<MobileShell />, rootStore)
|
||||
|
||||
// move to signin view
|
||||
fireEvent.press(getByTestId('signInButton'))
|
||||
expect(getByTestId('signIn')).toBeTruthy()
|
||||
expect(getByTestId('chooseAccountForm')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('logs directly into the account due to still possessing session tokens', async () => {
|
||||
const {getByTestId} = render(<MobileShell />, rootStore)
|
||||
|
||||
// move to signin view
|
||||
fireEvent.press(getByTestId('signInButton'))
|
||||
expect(getByTestId('signIn')).toBeTruthy()
|
||||
expect(getByTestId('chooseAccountForm')).toBeTruthy()
|
||||
|
||||
// select the previous account
|
||||
fireEvent.press(getByTestId('chooseAccountBtn-alice.test'))
|
||||
|
||||
// signs in immediately
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('homeFeed')).toBeTruthy()
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(1)
|
||||
}, WAIT_OPTS)
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(1)
|
||||
})
|
||||
|
||||
it('logs into a second account via the switcher', async () => {
|
||||
const {getByTestId, getAllByTestId} = render(<MobileShell />, rootStore)
|
||||
await waitFor(() => expect(getByTestId('homeFeed')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// open side menu
|
||||
fireEvent.press(getAllByTestId('viewHeaderBackOrMenuBtn')[0])
|
||||
await waitFor(() => expect(getByTestId('menuView')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// nav to settings
|
||||
fireEvent.press(getByTestId('menuItemButton-Settings'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('settingsScreen')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// press '+ new account' in switcher
|
||||
fireEvent.press(getByTestId('switchToNewAccountBtn'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('signinOrCreateAccount')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// move to signin view
|
||||
fireEvent.press(getByTestId('signInButton'))
|
||||
expect(getByTestId('signIn')).toBeTruthy()
|
||||
expect(getByTestId('chooseAccountForm')).toBeTruthy()
|
||||
|
||||
// select a new account
|
||||
fireEvent.press(getByTestId('chooseNewAccountBtn'))
|
||||
expect(getByTestId('loginForm')).toBeTruthy()
|
||||
|
||||
// input the target server
|
||||
expect(getByTestId('loginSelectServiceButton')).toBeTruthy()
|
||||
fireEvent.press(getByTestId('loginSelectServiceButton'))
|
||||
expect(getByTestId('serverInputModal')).toBeTruthy()
|
||||
fireEvent.changeText(
|
||||
getByTestId('customServerTextInput'),
|
||||
pds?.pdsUrl || '',
|
||||
)
|
||||
fireEvent.press(getByTestId('customServerSelectBtn'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('loginUsernameInput')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// enter username & pass
|
||||
fireEvent.changeText(getByTestId('loginUsernameInput'), 'bob')
|
||||
fireEvent.changeText(getByTestId('loginPasswordInput'), 'hunter2')
|
||||
await waitFor(
|
||||
() => expect(getByTestId('loginNextButton')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
fireEvent.press(getByTestId('loginNextButton'))
|
||||
|
||||
// signed in
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('homeFeed')).toBeTruthy() // we go back to settings in this situation
|
||||
expect(rootStore?.me?.displayName).toBe('Bob')
|
||||
expect(rootStore?.me?.handle).toBe('bob.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(2)
|
||||
}, WAIT_OPTS)
|
||||
expect(rootStore?.me?.displayName).toBe('Bob')
|
||||
expect(rootStore?.me?.handle).toBe('bob.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(2)
|
||||
})
|
||||
|
||||
it('can instantly switch between accounts', async () => {
|
||||
const {getAllByTestId, getByTestId} = render(<MobileShell />, rootStore)
|
||||
await waitFor(() => expect(getByTestId('homeFeed')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// open side menu
|
||||
fireEvent.press(getAllByTestId('viewHeaderBackOrMenuBtn')[0])
|
||||
await waitFor(() => expect(getByTestId('menuView')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// nav to settings
|
||||
fireEvent.press(getByTestId('menuItemButton-Settings'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('settingsScreen')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// select the alice account
|
||||
fireEvent.press(getByTestId('switchToAccountBtn-alice.test'))
|
||||
|
||||
// swapped account
|
||||
await waitFor(() => {
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(2)
|
||||
}, WAIT_OPTS)
|
||||
expect(rootStore?.me?.displayName).toBe('Alice')
|
||||
expect(rootStore?.me?.handle).toBe('alice.test')
|
||||
expect(rootStore?.session.accounts.length).toBe(2)
|
||||
})
|
||||
|
||||
it('will prompt for a password if you sign out', async () => {
|
||||
const {getAllByTestId, getByTestId} = render(<MobileShell />, rootStore)
|
||||
await waitFor(() => expect(getByTestId('homeFeed')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// open side menu
|
||||
fireEvent.press(getAllByTestId('viewHeaderBackOrMenuBtn')[0])
|
||||
await waitFor(() => expect(getByTestId('menuView')).toBeTruthy(), WAIT_OPTS)
|
||||
|
||||
// nav to settings
|
||||
fireEvent.press(getByTestId('menuItemButton-Settings'))
|
||||
await waitFor(
|
||||
() => expect(getByTestId('settingsScreen')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// press the sign out button
|
||||
fireEvent.press(getByTestId('signOutBtn'))
|
||||
|
||||
// in the logged out state
|
||||
await waitFor(
|
||||
() => expect(getByTestId('signinOrCreateAccount')).toBeTruthy(),
|
||||
WAIT_OPTS,
|
||||
)
|
||||
|
||||
// move to signin view
|
||||
fireEvent.press(getByTestId('signInButton'))
|
||||
expect(getByTestId('signIn')).toBeTruthy()
|
||||
expect(getByTestId('chooseAccountForm')).toBeTruthy()
|
||||
|
||||
// select an existing account
|
||||
fireEvent.press(getByTestId('chooseAccountBtn-alice.test'))
|
||||
|
||||
// goes to login screen instead of straight back to settings
|
||||
expect(getByTestId('loginForm')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
export const exampleComHtml = `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
<meta name="description" content="An example website">
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #f0f0f2;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
|
||||
}
|
||||
div {
|
||||
width: 600px;
|
||||
margin: 5em auto;
|
||||
padding: 2em;
|
||||
background-color: #fdfdff;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: #38488f;
|
||||
text-decoration: none;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
div {
|
||||
margin: 0 auto;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h1>Example Domain</h1>
|
||||
<p>This domain is for use in illustrative examples in documents. You may use this
|
||||
domain in literature without prior coordination or asking for permission.</p>
|
||||
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
@@ -0,0 +1,19 @@
|
||||
import {isNetworkError} from '../../src/lib/errors'
|
||||
|
||||
describe('isNetworkError', () => {
|
||||
const inputs = [
|
||||
'TypeError: Network request failed',
|
||||
'Uncaught TypeError: Cannot read property x of undefined',
|
||||
'Uncaught RangeError',
|
||||
'Error: Aborted',
|
||||
]
|
||||
const outputs = [true, false, false, true]
|
||||
|
||||
it('correctly distinguishes network errors', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const result = isNetworkError(input)
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,116 @@
|
||||
import {extractHtmlMeta} from '../../src/lib/extractHtmlMeta'
|
||||
import {exampleComHtml} from './__mocks__/exampleComHtml'
|
||||
import {youtubeHTML} from './__mocks__/youtubeHtml'
|
||||
import {tiktokHtml} from './__mocks__/tiktokHtml'
|
||||
|
||||
describe('extractHtmlMeta', () => {
|
||||
const cases = [
|
||||
['', {}],
|
||||
['nothing', {}],
|
||||
['<title>title</title>', {title: 'title'}],
|
||||
['<title> aSd!@#AC </title>', {title: 'aSd!@#AC'}],
|
||||
['<title>\n title\n </title>', {title: 'title'}],
|
||||
['<meta name="title" content="meta title">', {title: 'meta title'}],
|
||||
[
|
||||
'<meta name="description" content="meta description">',
|
||||
{description: 'meta description'},
|
||||
],
|
||||
['<meta property="og:title" content="og title">', {title: 'og title'}],
|
||||
[
|
||||
'<meta property="og:description" content="og description">',
|
||||
{description: 'og description'},
|
||||
],
|
||||
[
|
||||
'<meta property="og:image" content="https://ogimage.com/foo.png">',
|
||||
{image: 'https://ogimage.com/foo.png'},
|
||||
],
|
||||
[
|
||||
'<meta property="twitter:title" content="twitter title">',
|
||||
{title: 'twitter title'},
|
||||
],
|
||||
[
|
||||
'<meta property="twitter:description" content="twitter description">',
|
||||
{description: 'twitter description'},
|
||||
],
|
||||
[
|
||||
'<meta property="twitter:image" content="https://twitterimage.com/foo.png">',
|
||||
{image: 'https://twitterimage.com/foo.png'},
|
||||
],
|
||||
['<meta\n name="title"\n content="meta title"\n>', {title: 'meta title'}],
|
||||
]
|
||||
|
||||
it.each(cases)(
|
||||
'given the html tag %p, returns %p',
|
||||
(input, expectedResult) => {
|
||||
const output = extractHtmlMeta({html: input as string, hostname: ''})
|
||||
expect(output).toEqual(expectedResult)
|
||||
},
|
||||
)
|
||||
|
||||
it('extracts title and description from a generic HTML page', () => {
|
||||
const input = exampleComHtml
|
||||
const expectedOutput = {
|
||||
title: 'Example Domain',
|
||||
description: 'An example website',
|
||||
}
|
||||
const output = extractHtmlMeta({html: input, hostname: 'example.com'})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('extracts title and description from a Tiktok HTML page', () => {
|
||||
const input = tiktokHtml
|
||||
const expectedOutput = {
|
||||
title:
|
||||
'Coca-Cola and Mentos! Super Reaction! #cocacola #mentos #reaction #bal... | TikTok',
|
||||
description:
|
||||
'5.5M Likes, 20.8K Comments. TikTok video from Power Vision Tests (@_powervision_): "Coca-Cola and Mentos! Super Reaction! #cocacola #mentos #reaction #balloon #sciencemoment #scienceexperiment #experiment #test #amazing #pvexp". оригинальный звук - Power Vision Tests.',
|
||||
}
|
||||
const output = extractHtmlMeta({html: input, hostname: 'tiktok.com'})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('extracts title and description from a generic youtube page', () => {
|
||||
const input = youtubeHTML
|
||||
const expectedOutput = {
|
||||
title: 'HD Video (1080p) with Relaxing Music of Native American Shamans',
|
||||
description:
|
||||
'Stunning HD Video ( 1080p ) of Patagonian Nature with Relaxing Native American Shamanic Music. HD footage used from ',
|
||||
image: 'https://i.ytimg.com/vi/x6UITRjhijI/sddefault.jpg',
|
||||
}
|
||||
const output = extractHtmlMeta({html: input, hostname: 'youtube.com'})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('extracts username from the url a twitter profile page', () => {
|
||||
const expectedOutput = {
|
||||
title: '@bluesky on Twitter',
|
||||
}
|
||||
const output = extractHtmlMeta({
|
||||
hostname: 'twitter.com',
|
||||
pathname: '/bluesky',
|
||||
})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it('extracts username from the url a tweet', () => {
|
||||
const expectedOutput = {
|
||||
title: 'Tweet by @bluesky',
|
||||
}
|
||||
const output = extractHtmlMeta({
|
||||
hostname: 'twitter.com',
|
||||
pathname: '/bluesky/status/1582437529969917953',
|
||||
})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
it("does not extract username from the url when it's not a tweet or profile page", () => {
|
||||
const expectedOutput = {
|
||||
title: 'Twitter',
|
||||
}
|
||||
const output = extractHtmlMeta({
|
||||
hostname: 'twitter.com',
|
||||
pathname: '/i/articles/follows/-1675653703?time_window=24',
|
||||
})
|
||||
expect(output).toEqual(expectedOutput)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,93 @@
|
||||
import {downloadAndResize, DownloadAndResizeOpts} from '../../src/lib/images'
|
||||
import ImageResizer from '@bam.tech/react-native-image-resizer'
|
||||
import RNFetchBlob from 'rn-fetch-blob'
|
||||
|
||||
describe('downloadAndResize', () => {
|
||||
const errorSpy = jest.spyOn(global.console, 'error')
|
||||
|
||||
const mockResizedImage = {
|
||||
path: jest.fn().mockReturnValue('file://resized-image.jpg'),
|
||||
size: 100,
|
||||
width: 50,
|
||||
height: 50,
|
||||
mime: 'image/jpeg',
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
const mockedCreateResizedImage =
|
||||
ImageResizer.createResizedImage as jest.Mock
|
||||
mockedCreateResizedImage.mockResolvedValue(mockResizedImage)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should return resized image for valid URI and options', async () => {
|
||||
const mockedFetch = RNFetchBlob.fetch as jest.Mock
|
||||
mockedFetch.mockResolvedValueOnce({
|
||||
path: jest.fn().mockReturnValue('file://downloaded-image.jpg'),
|
||||
flush: jest.fn(),
|
||||
})
|
||||
|
||||
const opts: DownloadAndResizeOpts = {
|
||||
uri: 'https://example.com/image.jpg',
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxSize: 500000,
|
||||
mode: 'cover',
|
||||
timeout: 10000,
|
||||
}
|
||||
|
||||
const result = await downloadAndResize(opts)
|
||||
expect(result).toEqual(mockResizedImage)
|
||||
expect(RNFetchBlob.config).toHaveBeenCalledWith({
|
||||
fileCache: true,
|
||||
appendExt: 'jpeg',
|
||||
})
|
||||
expect(RNFetchBlob.fetch).toHaveBeenCalledWith(
|
||||
'GET',
|
||||
'https://example.com/image.jpg',
|
||||
)
|
||||
expect(ImageResizer.createResizedImage).toHaveBeenCalledWith(
|
||||
'file://downloaded-image.jpg',
|
||||
100,
|
||||
100,
|
||||
'JPEG',
|
||||
100,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{mode: 'cover'},
|
||||
)
|
||||
})
|
||||
|
||||
it('should return undefined for invalid URI', async () => {
|
||||
const opts: DownloadAndResizeOpts = {
|
||||
uri: 'invalid-uri',
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxSize: 500000,
|
||||
mode: 'cover',
|
||||
timeout: 10000,
|
||||
}
|
||||
|
||||
const result = await downloadAndResize(opts)
|
||||
expect(errorSpy).toHaveBeenCalled()
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined for unsupported file type', async () => {
|
||||
const opts: DownloadAndResizeOpts = {
|
||||
uri: 'https://example.com/image.bmp',
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxSize: 500000,
|
||||
mode: 'cover',
|
||||
timeout: 10000,
|
||||
}
|
||||
|
||||
const result = await downloadAndResize(opts)
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -1,52 +1,6 @@
|
||||
import {LikelyType, getLinkMeta} from '../src/lib/link-meta'
|
||||
|
||||
const exampleComHtml = `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
<meta name="description" content="An example website">
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #f0f0f2;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
|
||||
}
|
||||
div {
|
||||
width: 600px;
|
||||
margin: 5em auto;
|
||||
padding: 2em;
|
||||
background-color: #fdfdff;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: #38488f;
|
||||
text-decoration: none;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
div {
|
||||
margin: 0 auto;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h1>Example Domain</h1>
|
||||
<p>This domain is for use in illustrative examples in documents. You may use this
|
||||
domain in literature without prior coordination or asking for permission.</p>
|
||||
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
import {LikelyType, getLinkMeta, getLikelyType} from '../../src/lib/link-meta'
|
||||
import {exampleComHtml} from './__mocks__/exampleComHtml'
|
||||
import {mockedRootStore} from '../../__mocks__/state-mock'
|
||||
|
||||
describe('getLinkMeta', () => {
|
||||
const inputs = [
|
||||
@@ -57,7 +11,10 @@ describe('getLinkMeta', () => {
|
||||
'https://example.com/image.png',
|
||||
'https://example.com/video.avi',
|
||||
'https://example.com/audio.ogg',
|
||||
'https://example.com/text.txt',
|
||||
'https://example.com/javascript.js',
|
||||
'https://bsky.app/',
|
||||
'https://bsky.app/index.html',
|
||||
]
|
||||
const outputs = [
|
||||
{
|
||||
@@ -94,15 +51,35 @@ describe('getLinkMeta', () => {
|
||||
likelyType: LikelyType.Audio,
|
||||
url: 'https://example.com/audio.ogg',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.Text,
|
||||
url: 'https://example.com/text.txt',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.Other,
|
||||
url: 'https://example.com/javascript.js',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.AtpData,
|
||||
url: '/',
|
||||
title: 'Bluesky',
|
||||
description: 'A new kind of social network',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.AtpData,
|
||||
url: '/index.html',
|
||||
title: 'Not found',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.Other,
|
||||
url: '',
|
||||
title: '',
|
||||
},
|
||||
]
|
||||
it('correctly handles a set of text inputs', async () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
global.fetch = jest.fn().mockImplementationOnce(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, _reject) => {
|
||||
resolve({
|
||||
ok: true,
|
||||
status: 200,
|
||||
@@ -111,8 +88,20 @@ describe('getLinkMeta', () => {
|
||||
})
|
||||
})
|
||||
const input = inputs[i]
|
||||
const output = await getLinkMeta(input)
|
||||
const output = await getLinkMeta(mockedRootStore, input)
|
||||
expect(output).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('getLikelyType', () => {
|
||||
it('correctly handles non-parsed url', async () => {
|
||||
const output = await getLikelyType('https://example.com')
|
||||
expect(output).toEqual(LikelyType.HTML)
|
||||
})
|
||||
|
||||
it('handles non-string urls without crashing', async () => {
|
||||
const output = await getLikelyType('123')
|
||||
expect(output).toEqual(LikelyType.Other)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import {clamp} from '../../src/lib/numbers'
|
||||
|
||||
describe('clamp', () => {
|
||||
const inputs: [number, number, number][] = [
|
||||
[100, 0, 200],
|
||||
[100, 0, 100],
|
||||
[0, 0, 100],
|
||||
[100, 0, -1],
|
||||
[4, 1, 1],
|
||||
[100, -100, 0],
|
||||
[400, 100, -100],
|
||||
[70, -1, 1],
|
||||
[Infinity, Infinity, Infinity],
|
||||
]
|
||||
const outputs = [100, 100, 0, -1, 1, 0, -100, 1, Infinity]
|
||||
|
||||
it('correctly clamps any given number and range', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const result = clamp(...input)
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,17 @@
|
||||
import {
|
||||
extractEntities,
|
||||
detectLinkables,
|
||||
extractHtmlMeta,
|
||||
} from '../src/lib/strings'
|
||||
pluralize,
|
||||
makeRecordUri,
|
||||
ago,
|
||||
makeValidHandle,
|
||||
createFullHandle,
|
||||
enforceLen,
|
||||
cleanError,
|
||||
toNiceDomain,
|
||||
toShortUrl,
|
||||
toShareUrl,
|
||||
} from '../../src/lib/strings'
|
||||
|
||||
describe('extractEntities', () => {
|
||||
const knownHandles = new Set(['handle.com', 'full123.test-of-chars'])
|
||||
@@ -276,44 +285,205 @@ describe('detectLinkables', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('extractHtmlMeta', () => {
|
||||
const inputs = [
|
||||
'',
|
||||
'nothing',
|
||||
'<title>title</title>',
|
||||
'<title> aSd!@#AC </title>',
|
||||
'<title>\n title\n </title>',
|
||||
'<meta name="title" content="meta title">',
|
||||
'<meta name="description" content="meta description">',
|
||||
'<meta property="og:title" content="og title">',
|
||||
'<meta property="og:description" content="og description">',
|
||||
'<meta property="og:image" content="https://ogimage.com/foo.png">',
|
||||
'<meta property="twitter:title" content="twitter title">',
|
||||
'<meta property="twitter:description" content="twitter description">',
|
||||
'<meta property="twitter:image" content="https://twitterimage.com/foo.png">',
|
||||
'<meta\n name="title"\n content="meta title"\n>',
|
||||
describe('pluralize', () => {
|
||||
const inputs: [number, string, string?][] = [
|
||||
[1, 'follower'],
|
||||
[1, 'member'],
|
||||
[100, 'post'],
|
||||
[1000, 'repost'],
|
||||
[10000, 'upvote'],
|
||||
[100000, 'other'],
|
||||
[2, 'man', 'men'],
|
||||
]
|
||||
const outputs = [
|
||||
{},
|
||||
{},
|
||||
{title: 'title'},
|
||||
{title: 'aSd!@#AC'},
|
||||
{title: 'title'},
|
||||
{title: 'meta title'},
|
||||
{description: 'meta description'},
|
||||
{title: 'og title'},
|
||||
{description: 'og description'},
|
||||
{image: 'https://ogimage.com/foo.png'},
|
||||
{title: 'twitter title'},
|
||||
{description: 'twitter description'},
|
||||
{image: 'https://twitterimage.com/foo.png'},
|
||||
{title: 'meta title'},
|
||||
'follower',
|
||||
'member',
|
||||
'posts',
|
||||
'reposts',
|
||||
'upvotes',
|
||||
'others',
|
||||
'men',
|
||||
]
|
||||
it('correctly handles a set of text inputs', () => {
|
||||
|
||||
it('correctly pluralizes a set of words', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const output = extractHtmlMeta(input)
|
||||
const output = pluralize(...input)
|
||||
expect(output).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('makeRecordUri', () => {
|
||||
const inputs: [string, string, string][] = [
|
||||
['alice.test', 'app.bsky.feed.post', '3jk7x4irgv52r'],
|
||||
]
|
||||
const outputs = ['at://alice.test/app.bsky.feed.post/3jk7x4irgv52r']
|
||||
|
||||
it('correctly builds a record URI', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const result = makeRecordUri(...input)
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('ago', () => {
|
||||
const inputs = [
|
||||
1671461038,
|
||||
'04 Dec 1995 00:12:00 GMT',
|
||||
new Date(),
|
||||
new Date().setMinutes(new Date().getMinutes() - 10),
|
||||
new Date().setHours(new Date().getHours() - 1),
|
||||
new Date().setDate(new Date().getDate() - 1),
|
||||
new Date().setMonth(new Date().getMonth() - 1),
|
||||
]
|
||||
const outputs = [
|
||||
new Date(1671461038).toLocaleDateString(),
|
||||
new Date('04 Dec 1995 00:12:00 GMT').toLocaleDateString(),
|
||||
'0s',
|
||||
'10m',
|
||||
'1h',
|
||||
'1d',
|
||||
'1mo',
|
||||
]
|
||||
|
||||
it('correctly calculates how much time passed, in a string', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = ago(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('makeValidHandle', () => {
|
||||
const inputs = [
|
||||
'test-handle-123',
|
||||
'test!"#$%&/()=?_',
|
||||
'this-handle-should-be-too-big',
|
||||
]
|
||||
const outputs = ['test-handle-123', 'test', 'this-handle-should-b']
|
||||
|
||||
it('correctly parses and corrects handles', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = makeValidHandle(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('createFullHandle', () => {
|
||||
const inputs: [string, string][] = [
|
||||
['test-handle-123', 'test'],
|
||||
['.test.handle', 'test.test.'],
|
||||
['test.handle.', '.test.test'],
|
||||
]
|
||||
const outputs = [
|
||||
'test-handle-123.test',
|
||||
'.test.handle.test.test.',
|
||||
'test.handle.test.test',
|
||||
]
|
||||
|
||||
it('correctly parses and corrects handles', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const result = createFullHandle(...input)
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('enforceLen', () => {
|
||||
const inputs: [string, number][] = [
|
||||
['Hello World!', 5],
|
||||
['Hello World!', 20],
|
||||
['', 5],
|
||||
]
|
||||
const outputs = ['Hello', 'Hello World!', '']
|
||||
|
||||
it('correctly enforces defined length on a given string', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const result = enforceLen(...input)
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('cleanError', () => {
|
||||
const inputs = [
|
||||
'TypeError: Network request failed',
|
||||
'Error: Aborted',
|
||||
'Error: TypeError "x" is not a function',
|
||||
'Error: SyntaxError unexpected token "export"',
|
||||
'Some other error',
|
||||
]
|
||||
const outputs = [
|
||||
'Unable to connect. Please check your internet connection and try again.',
|
||||
'Unable to connect. Please check your internet connection and try again.',
|
||||
'TypeError "x" is not a function',
|
||||
'SyntaxError unexpected token "export"',
|
||||
'Some other error',
|
||||
]
|
||||
|
||||
it('removes extra content from error message', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = cleanError(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('toNiceDomain', () => {
|
||||
const inputs = [
|
||||
'https://example.com/index.html',
|
||||
'https://bsky.app',
|
||||
'https://bsky.social',
|
||||
'#123123123',
|
||||
]
|
||||
const outputs = ['example.com', 'bsky.app', 'Bluesky Social', '#123123123']
|
||||
|
||||
it("displays the url's host in a easily readable manner", () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = toNiceDomain(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('toShortUrl', () => {
|
||||
const inputs = [
|
||||
'https://bsky.app',
|
||||
'https://bsky.app/3jk7x4irgv52r',
|
||||
'https://bsky.app/3jk7x4irgv52r2313y182h9',
|
||||
]
|
||||
const outputs = [
|
||||
'bsky.app',
|
||||
'bsky.app/3jk7x4irgv52r',
|
||||
'bsky.app/3jk7x4irgv52r2313y...',
|
||||
]
|
||||
|
||||
it('shortens the url', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = toShortUrl(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('toShareUrl', () => {
|
||||
const inputs = ['https://bsky.app', '/3jk7x4irgv52r', 'item/test/123']
|
||||
const outputs = [
|
||||
'https://bsky.app',
|
||||
'https://bsky.app/3jk7x4irgv52r',
|
||||
'https://bsky.app/item/test/123',
|
||||
]
|
||||
|
||||
it('appends https, when not present', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const result = toShareUrl(inputs[i])
|
||||
expect(result).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,72 @@
|
||||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {LinkMetasViewModel} from '../../../src/state/models/link-metas-view'
|
||||
import * as LinkMetaLib from '../../../src/lib/link-meta'
|
||||
import {LikelyType} from './../../../src/lib/link-meta'
|
||||
import {sessionClient, SessionServiceClient} from '@atproto/api'
|
||||
import {DEFAULT_SERVICE} from '../../../src/state'
|
||||
|
||||
describe('LinkMetasViewModel', () => {
|
||||
let viewModel: LinkMetasViewModel
|
||||
let rootStore: RootStoreModel
|
||||
|
||||
const getLinkMetaMockSpy = jest.spyOn(LinkMetaLib, 'getLinkMeta')
|
||||
const mockedMeta = {
|
||||
title: 'Test Title',
|
||||
url: 'testurl',
|
||||
likelyType: LikelyType.Other,
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
const api = sessionClient.service(DEFAULT_SERVICE) as SessionServiceClient
|
||||
rootStore = new RootStoreModel(api)
|
||||
viewModel = new LinkMetasViewModel(rootStore)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('getLinkMeta', () => {
|
||||
it('should return link meta if it is cached', async () => {
|
||||
const url = 'http://example.com'
|
||||
|
||||
viewModel.cache.set(url, mockedMeta)
|
||||
|
||||
const result = await viewModel.getLinkMeta(url)
|
||||
|
||||
expect(getLinkMetaMockSpy).not.toHaveBeenCalled()
|
||||
expect(result).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should return link meta if it is not cached', async () => {
|
||||
getLinkMetaMockSpy.mockResolvedValueOnce(mockedMeta)
|
||||
|
||||
const result = await viewModel.getLinkMeta(mockedMeta.url)
|
||||
|
||||
expect(getLinkMetaMockSpy).toHaveBeenCalledWith(rootStore, mockedMeta.url)
|
||||
expect(result).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should cache the link meta if it is successfully returned', async () => {
|
||||
getLinkMetaMockSpy.mockResolvedValueOnce(mockedMeta)
|
||||
|
||||
await viewModel.getLinkMeta(mockedMeta.url)
|
||||
|
||||
expect(viewModel.cache.get(mockedMeta.url)).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should not cache the link meta if it fails to return', async () => {
|
||||
const url = 'http://example.com'
|
||||
const error = new Error('Failed to fetch link meta')
|
||||
getLinkMetaMockSpy.mockRejectedValueOnce(error)
|
||||
|
||||
try {
|
||||
await viewModel.getLinkMeta(url)
|
||||
fail('Error was not thrown')
|
||||
} catch (e) {
|
||||
expect(e).toEqual(error)
|
||||
expect(viewModel.cache.get(url)).toBeUndefined()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,153 @@
|
||||
import {LogModel} from '../../../src/state/models/log'
|
||||
|
||||
describe('LogModel', () => {
|
||||
let logModel: LogModel
|
||||
|
||||
beforeEach(() => {
|
||||
logModel = new LogModel()
|
||||
jest.spyOn(console, 'debug')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should call a log method and add a log entry to the entries array', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(logModel.entries.length).toEqual(1)
|
||||
expect(logModel.entries[0]).toEqual({
|
||||
id: logModel.entries[0].id,
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[0].ts,
|
||||
})
|
||||
|
||||
logModel.warn('Test log')
|
||||
expect(logModel.entries.length).toEqual(2)
|
||||
expect(logModel.entries[1]).toEqual({
|
||||
id: logModel.entries[1].id,
|
||||
type: 'warn',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[1].ts,
|
||||
})
|
||||
|
||||
logModel.error('Test log')
|
||||
expect(logModel.entries.length).toEqual(3)
|
||||
expect(logModel.entries[2]).toEqual({
|
||||
id: logModel.entries[2].id,
|
||||
type: 'error',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[2].ts,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the console.debug after calling the debug method', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(console.debug).toHaveBeenCalledWith('Test log', '')
|
||||
})
|
||||
|
||||
it('should call the serialize method', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(logModel.serialize()).toEqual({
|
||||
entries: [
|
||||
{
|
||||
id: logModel.entries[0].id,
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[0].ts,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the hydrate method with valid properties', () => {
|
||||
logModel.hydrate({
|
||||
entries: [
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(logModel.entries).toEqual([
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should call the hydrate method with invalid properties', () => {
|
||||
logModel.hydrate({
|
||||
entries: [
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
{
|
||||
summary: 'Invalid entry',
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(logModel.entries).toEqual([
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should stringify the details if it is not a string', () => {
|
||||
logModel.debug('Test log', {details: 'test'})
|
||||
expect(logModel.entries[0].details).toEqual('{\n "details": "test"\n}')
|
||||
})
|
||||
|
||||
it('should stringify the details object if it is of a specific error', () => {
|
||||
class TestError extends Error {
|
||||
constructor() {
|
||||
super()
|
||||
this.name = 'TestError'
|
||||
}
|
||||
}
|
||||
const error = new TestError()
|
||||
logModel.error('Test error log', error)
|
||||
expect(logModel.entries[0].details).toEqual('TestError')
|
||||
|
||||
class XRPCInvalidResponseErrorMock {
|
||||
validationError = {toString: () => 'validationError'}
|
||||
lexiconNsid = 'test'
|
||||
}
|
||||
const xrpcInvalidResponseError = new XRPCInvalidResponseErrorMock()
|
||||
logModel.error('Test error log', xrpcInvalidResponseError)
|
||||
expect(logModel.entries[1].details).toEqual(
|
||||
'{\n "validationError": {},\n "lexiconNsid": "test"\n}',
|
||||
)
|
||||
|
||||
class XRPCErrorMock {
|
||||
status = 'status'
|
||||
error = 'error'
|
||||
message = 'message'
|
||||
}
|
||||
const xrpcError = new XRPCErrorMock()
|
||||
logModel.error('Test error log', xrpcError)
|
||||
expect(logModel.entries[2].details).toEqual(
|
||||
'{\n "status": "status",\n "error": "error",\n "message": "message"\n}',
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,180 @@
|
||||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {MeModel} from '../../../src/state/models/me'
|
||||
import {NotificationsViewModel} from './../../../src/state/models/notifications-view'
|
||||
import {sessionClient, SessionServiceClient} from '@atproto/api'
|
||||
import {DEFAULT_SERVICE} from './../../../src/state/index'
|
||||
|
||||
describe('MeModel', () => {
|
||||
let rootStore: RootStoreModel
|
||||
let meModel: MeModel
|
||||
|
||||
beforeEach(() => {
|
||||
const api = sessionClient.service(DEFAULT_SERVICE) as SessionServiceClient
|
||||
rootStore = new RootStoreModel(api)
|
||||
meModel = new MeModel(rootStore)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should clear() correctly', () => {
|
||||
meModel.did = '123'
|
||||
meModel.handle = 'handle'
|
||||
meModel.displayName = 'John Doe'
|
||||
meModel.description = 'description'
|
||||
meModel.avatar = 'avatar'
|
||||
meModel.notificationCount = 1
|
||||
meModel.clear()
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
expect(meModel.notificationCount).toEqual(0)
|
||||
})
|
||||
|
||||
it('should hydrate() successfully with valid properties', () => {
|
||||
meModel.hydrate({
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('John Doe')
|
||||
expect(meModel.description).toEqual('description')
|
||||
expect(meModel.avatar).toEqual('avatar')
|
||||
})
|
||||
|
||||
it('should not hydrate() with invalid properties', () => {
|
||||
meModel.hydrate({
|
||||
did: '',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
|
||||
meModel.hydrate({
|
||||
did: '123',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
})
|
||||
|
||||
it('should load() successfully', async () => {
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.actor, 'getProfile')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
},
|
||||
})
|
||||
})
|
||||
rootStore.session.data = {
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
service: 'test service',
|
||||
accessJwt: 'test token',
|
||||
refreshJwt: 'test token',
|
||||
}
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('John Doe')
|
||||
expect(meModel.description).toEqual('description')
|
||||
expect(meModel.avatar).toEqual('avatar')
|
||||
})
|
||||
|
||||
it('should load() successfully without profile data', async () => {
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.actor, 'getProfile')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: null,
|
||||
})
|
||||
})
|
||||
rootStore.session.data = {
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
service: 'test service',
|
||||
accessJwt: 'test token',
|
||||
refreshJwt: 'test token',
|
||||
}
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
})
|
||||
|
||||
it('should load() to nothing when no session', async () => {
|
||||
rootStore.session.data = null
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
expect(meModel.notificationCount).toEqual(0)
|
||||
})
|
||||
|
||||
it('should serialize() key information', () => {
|
||||
meModel.did = '123'
|
||||
meModel.handle = 'handle'
|
||||
meModel.displayName = 'John Doe'
|
||||
meModel.description = 'description'
|
||||
meModel.avatar = 'avatar'
|
||||
|
||||
expect(meModel.serialize()).toEqual({
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
})
|
||||
|
||||
it('should clearNotificationCount() successfully', () => {
|
||||
meModel.clearNotificationCount()
|
||||
expect(meModel.notificationCount).toBe(0)
|
||||
})
|
||||
|
||||
it('should update notifs count with fetchStateUpdate()', async () => {
|
||||
meModel.notifications = {
|
||||
refresh: jest.fn().mockResolvedValue({}),
|
||||
} as unknown as NotificationsViewModel
|
||||
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.notification, 'getCount')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
count: 1,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
await meModel.fetchNotifications()
|
||||
expect(meModel.notificationCount).toBe(1)
|
||||
expect(meModel.notifications.refresh).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,151 @@
|
||||
import {NavigationModel} from './../../../src/state/models/navigation'
|
||||
import * as flags from '../../../src/build-flags'
|
||||
|
||||
describe('NavigationModel', () => {
|
||||
let model: NavigationModel
|
||||
|
||||
beforeEach(() => {
|
||||
model = new NavigationModel()
|
||||
model.setTitle('0-0', 'title')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should clear() to the correct base state', async () => {
|
||||
await model.clear()
|
||||
expect(model.tabCount).toBe(2)
|
||||
expect(model.tab).toEqual({
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the navigate method', async () => {
|
||||
const navigateSpy = jest.spyOn(model.tab, 'navigate')
|
||||
await model.navigate('testurl', 'teststring')
|
||||
expect(navigateSpy).toHaveBeenCalledWith('testurl', 'teststring')
|
||||
})
|
||||
|
||||
it('should call the refresh method', async () => {
|
||||
const refreshSpy = jest.spyOn(model.tab, 'refresh')
|
||||
await model.refresh()
|
||||
expect(refreshSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should call the isCurrentScreen method', () => {
|
||||
expect(model.isCurrentScreen('11', 0)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should call the tab getter', () => {
|
||||
expect(model.tab).toEqual({
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the tabCount getter', () => {
|
||||
expect(model.tabCount).toBe(2)
|
||||
})
|
||||
|
||||
describe('tabs not enabled', () => {
|
||||
jest.mock('../../../src/build-flags', () => ({
|
||||
TABS_ENABLED: false,
|
||||
}))
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should not create new tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.newTab('testurl')
|
||||
expect(model.tab.isNewTab).toBe(false)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should not change the active tab', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.setActiveTab(2)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should note close tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.closeTab(0)
|
||||
expect(model.tabCount).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('tabs enabled', () => {
|
||||
jest.mock('../../../src/build-flags', () => ({
|
||||
TABS_ENABLED: true,
|
||||
}))
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should create new tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.newTab('testurl', 'title')
|
||||
expect(model.tab.isNewTab).toBe(true)
|
||||
expect(model.tabIndex).toBe(2)
|
||||
})
|
||||
|
||||
it('should change the current tab', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.setActiveTab(0)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should close tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.closeTab(0)
|
||||
expect(model.tabs).toEqual([
|
||||
{
|
||||
fixedTabPurpose: 1,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/notifications',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
])
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
OnboardModel,
|
||||
OnboardStageOrder,
|
||||
} from '../../../src/state/models/onboard'
|
||||
|
||||
describe('OnboardModel', () => {
|
||||
let onboardModel: OnboardModel
|
||||
|
||||
beforeEach(() => {
|
||||
onboardModel = new OnboardModel()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should start/stop correctly', () => {
|
||||
onboardModel.start()
|
||||
expect(onboardModel.isOnboarding).toBe(true)
|
||||
onboardModel.stop()
|
||||
expect(onboardModel.isOnboarding).toBe(false)
|
||||
})
|
||||
|
||||
it('should call the next method until it has no more stages', () => {
|
||||
onboardModel.start()
|
||||
onboardModel.next()
|
||||
expect(onboardModel.stage).toBe(OnboardStageOrder[1])
|
||||
|
||||
onboardModel.next()
|
||||
expect(onboardModel.isOnboarding).toBe(false)
|
||||
expect(onboardModel.stage).toBe(OnboardStageOrder[0])
|
||||
})
|
||||
|
||||
it('serialize and hydrate', () => {
|
||||
const serialized = onboardModel.serialize()
|
||||
const newModel = new OnboardModel()
|
||||
newModel.hydrate(serialized)
|
||||
expect(newModel).toEqual(onboardModel)
|
||||
|
||||
onboardModel.start()
|
||||
onboardModel.next()
|
||||
const serialized2 = onboardModel.serialize()
|
||||
newModel.hydrate(serialized2)
|
||||
expect(newModel).toEqual(onboardModel)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,59 @@
|
||||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {setupState} from '../../../src/state'
|
||||
|
||||
describe('rootStore', () => {
|
||||
let rootStore: RootStoreModel
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
rootStore = await setupState()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should call the clearAll() resets state correctly', () => {
|
||||
rootStore.clearAll()
|
||||
|
||||
expect(rootStore.session.data).toEqual(null)
|
||||
expect(rootStore.nav.tabs).toEqual([
|
||||
{
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
{
|
||||
fixedTabPurpose: 1,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/notifications',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
])
|
||||
expect(rootStore.nav.tabIndex).toEqual(0)
|
||||
expect(rootStore.me.did).toEqual('')
|
||||
expect(rootStore.me.handle).toEqual('')
|
||||
expect(rootStore.me.displayName).toEqual('')
|
||||
expect(rootStore.me.description).toEqual('')
|
||||
expect(rootStore.me.avatar).toEqual('')
|
||||
expect(rootStore.me.notificationCount).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
ConfirmModal,
|
||||
ImagesLightbox,
|
||||
ShellUiModel,
|
||||
} from './../../../src/state/models/shell-ui'
|
||||
|
||||
describe('ShellUiModel', () => {
|
||||
let model: ShellUiModel
|
||||
|
||||
beforeEach(() => {
|
||||
model = new ShellUiModel()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should call the openModal & closeModal method', () => {
|
||||
const m = new ConfirmModal('Test Modal', 'Look good?', () => {})
|
||||
model.openModal(m)
|
||||
expect(model.isModalActive).toEqual(true)
|
||||
expect(model.activeModal).toEqual(m)
|
||||
|
||||
model.closeModal()
|
||||
expect(model.isModalActive).toEqual(false)
|
||||
expect(model.activeModal).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should call the openLightbox & closeLightbox method', () => {
|
||||
const lt = new ImagesLightbox(['uri'], 0)
|
||||
model.openLightbox(lt)
|
||||
expect(model.isLightboxActive).toEqual(true)
|
||||
expect(model.activeLightbox).toEqual(lt)
|
||||
|
||||
model.closeLightbox()
|
||||
expect(model.isLightboxActive).toEqual(false)
|
||||
expect(model.activeLightbox).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should call the openComposer & closeComposer method', () => {
|
||||
const composer = {
|
||||
replyTo: {
|
||||
uri: 'uri',
|
||||
cid: 'cid',
|
||||
text: 'text',
|
||||
author: {
|
||||
handle: 'handle',
|
||||
displayName: 'name',
|
||||
},
|
||||
},
|
||||
onPost: jest.fn(),
|
||||
}
|
||||
model.openComposer(composer)
|
||||
expect(model.isComposerActive).toEqual(true)
|
||||
expect(model.composerOpts).toEqual(composer)
|
||||
|
||||
model.closeComposer()
|
||||
expect(model.isComposerActive).toEqual(false)
|
||||
expect(model.composerOpts).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react'
|
||||
import {Autocomplete} from '../../../../src/view/com/composer/Autocomplete'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
|
||||
describe('Autocomplete', () => {
|
||||
const onSelectMock = jest.fn()
|
||||
const mockedProps = {
|
||||
active: true,
|
||||
items: [
|
||||
{
|
||||
handle: 'handle.test',
|
||||
displayName: 'Test Display',
|
||||
},
|
||||
{
|
||||
handle: 'handle2.test',
|
||||
displayName: 'Test Display 2',
|
||||
},
|
||||
],
|
||||
onSelect: onSelectMock,
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders a button for each user', async () => {
|
||||
const {findAllByTestId} = render(<Autocomplete {...mockedProps} />)
|
||||
const autocompleteButton = await findAllByTestId('autocompleteButton')
|
||||
expect(autocompleteButton.length).toBe(2)
|
||||
})
|
||||
|
||||
it('triggers onSelect by pressing the button', async () => {
|
||||
const {findAllByTestId} = render(<Autocomplete {...mockedProps} />)
|
||||
const autocompleteButton = await findAllByTestId('autocompleteButton')
|
||||
|
||||
fireEvent.press(autocompleteButton[0])
|
||||
expect(onSelectMock).toHaveBeenCalledWith('handle.test')
|
||||
|
||||
fireEvent.press(autocompleteButton[1])
|
||||
expect(onSelectMock).toHaveBeenCalledWith('handle2.test')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import {ComposePost} from '../../../../src/view/com/composer/ComposePost'
|
||||
import {cleanup, fireEvent, render, waitFor} from '../../../../jest/test-utils'
|
||||
import * as apilib from '../../../../src/state/lib/api'
|
||||
import {
|
||||
mockedAutocompleteViewStore,
|
||||
mockedRootStore,
|
||||
} from '../../../../__mocks__/state-mock'
|
||||
import Toast from 'react-native-root-toast'
|
||||
|
||||
describe('ComposePost', () => {
|
||||
const mockedProps = {
|
||||
replyTo: {
|
||||
uri: 'testUri',
|
||||
cid: 'testCid',
|
||||
text: 'testText',
|
||||
author: {
|
||||
handle: 'test.handle',
|
||||
displayName: 'test name',
|
||||
avatar: '',
|
||||
},
|
||||
},
|
||||
onPost: jest.fn(),
|
||||
onClose: jest.fn(),
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders post composer', async () => {
|
||||
const {findByTestId} = render(<ComposePost {...mockedProps} />)
|
||||
const composePostView = await findByTestId('composePostView')
|
||||
expect(composePostView).toBeTruthy()
|
||||
})
|
||||
|
||||
it('closes composer', async () => {
|
||||
const {findByTestId} = render(<ComposePost {...mockedProps} />)
|
||||
const composerCancelButton = await findByTestId('composerCancelButton')
|
||||
fireEvent.press(composerCancelButton)
|
||||
expect(mockedProps.onClose).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('changes text and publishes post', async () => {
|
||||
const postSpy = jest.spyOn(apilib, 'post').mockResolvedValue({
|
||||
uri: '',
|
||||
cid: '',
|
||||
})
|
||||
const toastSpy = jest.spyOn(Toast, 'show')
|
||||
|
||||
const wrapper = render(<ComposePost {...mockedProps} />)
|
||||
|
||||
const composerTextInput = await wrapper.findByTestId('composerTextInput')
|
||||
fireEvent.changeText(composerTextInput, 'testing publish')
|
||||
|
||||
const composerPublishButton = await wrapper.findByTestId(
|
||||
'composerPublishButton',
|
||||
)
|
||||
fireEvent.press(composerPublishButton)
|
||||
|
||||
expect(postSpy).toHaveBeenCalledWith(
|
||||
mockedRootStore,
|
||||
'testing publish',
|
||||
'testUri',
|
||||
undefined,
|
||||
[],
|
||||
new Set<string>(),
|
||||
expect.anything(),
|
||||
)
|
||||
|
||||
// Waits for request to be resolved
|
||||
await waitFor(() => {
|
||||
expect(mockedProps.onPost).toHaveBeenCalled()
|
||||
expect(mockedProps.onClose).toHaveBeenCalled()
|
||||
expect(toastSpy).toHaveBeenCalledWith('Your reply has been published', {
|
||||
animation: true,
|
||||
duration: 3500,
|
||||
hideOnPress: true,
|
||||
position: 50,
|
||||
shadow: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('selects autocomplete item', async () => {
|
||||
jest
|
||||
.spyOn(React, 'useMemo')
|
||||
.mockReturnValueOnce(mockedAutocompleteViewStore)
|
||||
|
||||
const {findAllByTestId} = render(<ComposePost {...mockedProps} />)
|
||||
const autocompleteButton = await findAllByTestId('autocompleteButton')
|
||||
|
||||
fireEvent.press(autocompleteButton[0])
|
||||
expect(mockedAutocompleteViewStore.setActive).toHaveBeenCalledWith(false)
|
||||
})
|
||||
|
||||
it('selects photos', async () => {
|
||||
const {findByTestId, queryByTestId} = render(
|
||||
<ComposePost {...mockedProps} />,
|
||||
)
|
||||
let photoCarouselPickerView = queryByTestId('photoCarouselPickerView')
|
||||
expect(photoCarouselPickerView).toBeFalsy()
|
||||
|
||||
const composerSelectPhotosButton = await findByTestId(
|
||||
'composerSelectPhotosButton',
|
||||
)
|
||||
fireEvent.press(composerSelectPhotosButton)
|
||||
|
||||
photoCarouselPickerView = await findByTestId('photoCarouselPickerView')
|
||||
expect(photoCarouselPickerView).toBeTruthy()
|
||||
|
||||
fireEvent.press(composerSelectPhotosButton)
|
||||
|
||||
photoCarouselPickerView = queryByTestId('photoCarouselPickerView')
|
||||
expect(photoCarouselPickerView).toBeFalsy()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,70 @@
|
||||
import React from 'react'
|
||||
import {SelectedPhoto} from '../../../../src/view/com/composer/SelectedPhoto'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
|
||||
describe('SelectedPhoto', () => {
|
||||
const mockedProps = {
|
||||
selectedPhotos: ['mock-uri', 'mock-uri-2'],
|
||||
onSelectPhotos: jest.fn(),
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('has no photos to render', () => {
|
||||
const {queryByTestId} = render(
|
||||
<SelectedPhoto selectedPhotos={[]} onSelectPhotos={jest.fn()} />,
|
||||
)
|
||||
const selectedPhotosView = queryByTestId('selectedPhotosView')
|
||||
expect(selectedPhotosView).toBeNull()
|
||||
|
||||
const selectedPhotoImage = queryByTestId('selectedPhotoImage')
|
||||
expect(selectedPhotoImage).toBeNull()
|
||||
})
|
||||
|
||||
it('has 1 photos to render', async () => {
|
||||
const {findByTestId} = render(
|
||||
<SelectedPhoto
|
||||
selectedPhotos={['mock-uri']}
|
||||
onSelectPhotos={jest.fn()}
|
||||
/>,
|
||||
)
|
||||
const selectedPhotosView = await findByTestId('selectedPhotosView')
|
||||
expect(selectedPhotosView).toBeTruthy()
|
||||
|
||||
const selectedPhotoImage = await findByTestId('selectedPhotoImage')
|
||||
expect(selectedPhotoImage).toBeTruthy()
|
||||
// @ts-expect-error
|
||||
expect(selectedPhotoImage).toHaveStyle({width: 250})
|
||||
})
|
||||
|
||||
it('has 2 photos to render', async () => {
|
||||
const {findAllByTestId} = render(<SelectedPhoto {...mockedProps} />)
|
||||
const selectedPhotoImage = await findAllByTestId('selectedPhotoImage')
|
||||
expect(selectedPhotoImage[0]).toBeTruthy()
|
||||
// @ts-expect-error
|
||||
expect(selectedPhotoImage[0]).toHaveStyle({width: 175})
|
||||
})
|
||||
|
||||
it('has 3 photos to render', async () => {
|
||||
const {findAllByTestId} = render(
|
||||
<SelectedPhoto
|
||||
selectedPhotos={['mock-uri', 'mock-uri-2', 'mock-uri-3']}
|
||||
onSelectPhotos={jest.fn()}
|
||||
/>,
|
||||
)
|
||||
const selectedPhotoImage = await findAllByTestId('selectedPhotoImage')
|
||||
expect(selectedPhotoImage[0]).toBeTruthy()
|
||||
// @ts-expect-error
|
||||
expect(selectedPhotoImage[0]).toHaveStyle({width: 85})
|
||||
})
|
||||
|
||||
it('removes a photo', async () => {
|
||||
const {findAllByTestId} = render(<SelectedPhoto {...mockedProps} />)
|
||||
const removePhotoButton = await findAllByTestId('removePhotoButton')
|
||||
fireEvent.press(removePhotoButton[0])
|
||||
expect(mockedProps.onSelectPhotos).toHaveBeenCalledWith(['mock-uri-2'])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
import React from 'react'
|
||||
import {Keyboard} from 'react-native'
|
||||
import {CreateAccount} from '../../../../src/view/com/login/CreateAccount'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
import {
|
||||
mockedSessionStore,
|
||||
mockedShellStore,
|
||||
} from '../../../../__mocks__/state-mock'
|
||||
|
||||
describe('CreateAccount', () => {
|
||||
const mockedProps = {
|
||||
onPressBack: jest.fn(),
|
||||
}
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders form and creates new account', async () => {
|
||||
const {findByTestId} = render(<CreateAccount {...mockedProps} />)
|
||||
|
||||
const registerEmailInput = await findByTestId('registerEmailInput')
|
||||
expect(registerEmailInput).toBeTruthy()
|
||||
fireEvent.changeText(registerEmailInput, 'test@email.com')
|
||||
|
||||
const registerHandleInput = await findByTestId('registerHandleInput')
|
||||
expect(registerHandleInput).toBeTruthy()
|
||||
fireEvent.changeText(registerHandleInput, 'test.handle')
|
||||
|
||||
const registerPasswordInput = await findByTestId('registerPasswordInput')
|
||||
expect(registerPasswordInput).toBeTruthy()
|
||||
fireEvent.changeText(registerPasswordInput, 'testpass')
|
||||
|
||||
const registerIs13Input = await findByTestId('registerIs13Input')
|
||||
expect(registerIs13Input).toBeTruthy()
|
||||
fireEvent.press(registerIs13Input)
|
||||
|
||||
const createAccountButton = await findByTestId('createAccountButton')
|
||||
expect(createAccountButton).toBeTruthy()
|
||||
fireEvent.press(createAccountButton)
|
||||
|
||||
expect(mockedSessionStore.createAccount).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('renders and selects service', async () => {
|
||||
const keyboardSpy = jest.spyOn(Keyboard, 'dismiss')
|
||||
const {findByTestId} = render(<CreateAccount {...mockedProps} />)
|
||||
|
||||
const registerSelectServiceButton = await findByTestId(
|
||||
'registerSelectServiceButton',
|
||||
)
|
||||
expect(registerSelectServiceButton).toBeTruthy()
|
||||
fireEvent.press(registerSelectServiceButton)
|
||||
|
||||
expect(mockedShellStore.openModal).toHaveBeenCalled()
|
||||
expect(keyboardSpy).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,110 @@
|
||||
import React from 'react'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
import {ProfileViewModel} from '../../../../src/state/models/profile-view'
|
||||
import {ProfileHeader} from '../../../../src/view/com/profile/ProfileHeader'
|
||||
import {
|
||||
mockedNavigationStore,
|
||||
mockedProfileStore,
|
||||
mockedShellStore,
|
||||
} from '../../../../__mocks__/state-mock'
|
||||
|
||||
describe('ProfileHeader', () => {
|
||||
const mockedProps = {
|
||||
view: mockedProfileStore,
|
||||
onRefreshAll: jest.fn(),
|
||||
}
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders ErrorMessage on error', async () => {
|
||||
const {findByTestId} = render(
|
||||
<ProfileHeader
|
||||
{...{
|
||||
view: {
|
||||
...mockedProfileStore,
|
||||
hasError: true,
|
||||
} as ProfileViewModel,
|
||||
onRefreshAll: jest.fn(),
|
||||
}}
|
||||
/>,
|
||||
)
|
||||
|
||||
const profileHeaderHasError = await findByTestId('profileHeaderHasError')
|
||||
expect(profileHeaderHasError).toBeTruthy()
|
||||
})
|
||||
|
||||
it('presses and opens edit profile', async () => {
|
||||
const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
|
||||
|
||||
const profileHeaderEditProfileButton = await findByTestId(
|
||||
'profileHeaderEditProfileButton',
|
||||
)
|
||||
expect(profileHeaderEditProfileButton).toBeTruthy()
|
||||
fireEvent.press(profileHeaderEditProfileButton)
|
||||
|
||||
expect(mockedShellStore.openModal).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('presses and opens followers page', async () => {
|
||||
const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
|
||||
|
||||
const profileHeaderFollowersButton = await findByTestId(
|
||||
'profileHeaderFollowersButton',
|
||||
)
|
||||
expect(profileHeaderFollowersButton).toBeTruthy()
|
||||
fireEvent.press(profileHeaderFollowersButton)
|
||||
|
||||
expect(mockedNavigationStore.navigate).toHaveBeenCalledWith(
|
||||
'/profile/testhandle/followers',
|
||||
)
|
||||
})
|
||||
|
||||
// TODO - this will only pass if the profile has an avatar image set
|
||||
// it('presses and opens avatar modal', async () => {
|
||||
// const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
|
||||
|
||||
// const profileHeaderAviButton = await findByTestId('profileHeaderAviButton')
|
||||
// expect(profileHeaderAviButton).toBeTruthy()
|
||||
// fireEvent.press(profileHeaderAviButton)
|
||||
|
||||
// expect(mockedShellStore.openLightbox).toHaveBeenCalled()
|
||||
// })
|
||||
|
||||
it('presses and opens follows page', async () => {
|
||||
const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
|
||||
|
||||
const profileHeaderFollowsButton = await findByTestId(
|
||||
'profileHeaderFollowsButton',
|
||||
)
|
||||
expect(profileHeaderFollowsButton).toBeTruthy()
|
||||
fireEvent.press(profileHeaderFollowsButton)
|
||||
|
||||
expect(mockedNavigationStore.navigate).toHaveBeenCalledWith(
|
||||
'/profile/testhandle/follows',
|
||||
)
|
||||
})
|
||||
|
||||
it('toggles following', async () => {
|
||||
const {findByTestId} = render(
|
||||
<ProfileHeader
|
||||
{...{
|
||||
view: {
|
||||
...mockedProfileStore,
|
||||
did: 'test did 2',
|
||||
} as ProfileViewModel,
|
||||
onRefreshAll: jest.fn(),
|
||||
}}
|
||||
/>,
|
||||
)
|
||||
|
||||
const profileHeaderToggleFollowButton = await findByTestId(
|
||||
'profileHeaderToggleFollowButton',
|
||||
)
|
||||
expect(profileHeaderToggleFollowButton).toBeTruthy()
|
||||
fireEvent.press(profileHeaderToggleFollowButton)
|
||||
|
||||
expect(mockedProps.view.toggleFollowing).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
import {renderHook} from '../../../jest/test-utils'
|
||||
import {useAnimatedValue} from '../../../src/view/lib/hooks/useAnimatedValue'
|
||||
|
||||
describe('useAnimatedValue', () => {
|
||||
it('creates an Animated.Value with the initial value passed to the hook', () => {
|
||||
const {result} = renderHook(() => useAnimatedValue(10))
|
||||
// @ts-expect-error
|
||||
expect(result.current.__getValue()).toEqual(10)
|
||||
})
|
||||
|
||||
it('returns the same Animated.Value instance on subsequent renders', () => {
|
||||
const {result, rerender} = renderHook(() => useAnimatedValue(10))
|
||||
const firstValue = result.current
|
||||
rerender({})
|
||||
expect(result.current).toBe(firstValue)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,49 @@
|
||||
import React from 'react'
|
||||
import {fireEvent, render} from '../../../jest/test-utils'
|
||||
import {Home} from '../../../src/view/screens/Home'
|
||||
import {mockedRootStore, mockedShellStore} from '../../../__mocks__/state-mock'
|
||||
|
||||
describe('useOnMainScroll', () => {
|
||||
const mockedProps = {
|
||||
navIdx: [0, 0] as [number, number],
|
||||
params: {},
|
||||
visible: true,
|
||||
}
|
||||
|
||||
it('toggles minimalShellMode to true', () => {
|
||||
jest.useFakeTimers()
|
||||
const {getByTestId} = render(<Home {...mockedProps} />)
|
||||
|
||||
fireEvent.scroll(getByTestId('homeFeed'), {
|
||||
nativeEvent: {
|
||||
contentOffset: {y: 20},
|
||||
contentSize: {height: 100},
|
||||
layoutMeasurement: {height: 50},
|
||||
},
|
||||
})
|
||||
|
||||
expect(mockedRootStore.shell.setMinimalShellMode).toHaveBeenCalledWith(true)
|
||||
})
|
||||
|
||||
it('toggles minimalShellMode to false', () => {
|
||||
jest.useFakeTimers()
|
||||
const {getByTestId} = render(<Home {...mockedProps} />, {
|
||||
...mockedRootStore,
|
||||
shell: {
|
||||
...mockedShellStore,
|
||||
minimalShellMode: true,
|
||||
},
|
||||
})
|
||||
|
||||
fireEvent.scroll(getByTestId('homeFeed'), {
|
||||
nativeEvent: {
|
||||
contentOffset: {y: 0},
|
||||
contentSize: {height: 100},
|
||||
layoutMeasurement: {height: 50},
|
||||
},
|
||||
})
|
||||
expect(mockedRootStore.shell.setMinimalShellMode).toHaveBeenCalledWith(
|
||||
false,
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react'
|
||||
import {Login} from '../../../src/view/screens/Login'
|
||||
import {cleanup, fireEvent, render} from '../../../jest/test-utils'
|
||||
|
||||
describe('Login', () => {
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders initial screen', () => {
|
||||
const {getByTestId} = render(<Login />)
|
||||
const signUpScreen = getByTestId('signinOrCreateAccount')
|
||||
|
||||
expect(signUpScreen).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders Signin screen', () => {
|
||||
const {getByTestId} = render(<Login />)
|
||||
const signInButton = getByTestId('signInButton')
|
||||
|
||||
fireEvent.press(signInButton)
|
||||
|
||||
const signInScreen = getByTestId('signIn')
|
||||
expect(signInScreen).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders CreateAccount screen', () => {
|
||||
const {getByTestId} = render(<Login />)
|
||||
const createAccountButton = getByTestId('createAccountButton')
|
||||
|
||||
fireEvent.press(createAccountButton)
|
||||
|
||||
const createAccountScreen = getByTestId('createAccount')
|
||||
expect(createAccountScreen).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import {NotFound} from '../../../src/view/screens/NotFound'
|
||||
import {cleanup, fireEvent, render} from '../../../jest/test-utils'
|
||||
import {mockedNavigationStore} from '../../../__mocks__/state-mock'
|
||||
|
||||
describe('NotFound', () => {
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('navigates home', async () => {
|
||||
const navigationSpy = jest.spyOn(mockedNavigationStore, 'navigate')
|
||||
const {getByTestId} = render(<NotFound />)
|
||||
const navigateHomeButton = getByTestId('navigateHomeButton')
|
||||
|
||||
fireEvent.press(navigateHomeButton)
|
||||
|
||||
expect(navigationSpy).toHaveBeenCalledWith('/')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from 'react'
|
||||
import {Search} from '../../../src/view/screens/Search'
|
||||
import {cleanup, fireEvent, render} from '../../../jest/test-utils'
|
||||
|
||||
describe('Search', () => {
|
||||
jest.useFakeTimers()
|
||||
const mockedProps = {
|
||||
navIdx: [0, 0] as [number, number],
|
||||
params: {
|
||||
name: 'test name',
|
||||
},
|
||||
visible: true,
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders with query', async () => {
|
||||
const {findByTestId} = render(<Search {...mockedProps} />)
|
||||
const searchTextInput = await findByTestId('searchTextInput')
|
||||
|
||||
expect(searchTextInput).toBeTruthy()
|
||||
fireEvent.changeText(searchTextInput, 'test')
|
||||
|
||||
const searchScrollView = await findByTestId('searchScrollView')
|
||||
expect(searchScrollView).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from 'react'
|
||||
import {Menu} from '../../../../src/view/shell/mobile/Menu'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
import {mockedNavigationStore} from '../../../../__mocks__/state-mock'
|
||||
|
||||
describe('Menu', () => {
|
||||
const onCloseMock = jest.fn()
|
||||
|
||||
const mockedProps = {
|
||||
visible: true,
|
||||
onClose: onCloseMock,
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders menu', () => {
|
||||
const {getByTestId} = render(<Menu {...mockedProps} />)
|
||||
|
||||
const menuView = getByTestId('menuView')
|
||||
|
||||
expect(menuView).toBeTruthy()
|
||||
})
|
||||
|
||||
it('presses profile card button', () => {
|
||||
const {getByTestId} = render(<Menu {...mockedProps} />)
|
||||
|
||||
const profileCardButton = getByTestId('profileCardButton')
|
||||
fireEvent.press(profileCardButton)
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.switchTo).toHaveBeenCalledWith(0, true)
|
||||
})
|
||||
|
||||
it('presses search button', () => {
|
||||
const {getByTestId} = render(<Menu {...mockedProps} />)
|
||||
|
||||
const searchBtn = getByTestId('searchBtn')
|
||||
fireEvent.press(searchBtn)
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.switchTo).toHaveBeenCalledWith(0, true)
|
||||
expect(mockedNavigationStore.navigate).toHaveBeenCalledWith('/search')
|
||||
})
|
||||
|
||||
it("presses notifications menu item' button", () => {
|
||||
const {getByTestId} = render(<Menu {...mockedProps} />)
|
||||
|
||||
const menuItemButton = getByTestId('menuItemButton-Notifications')
|
||||
fireEvent.press(menuItemButton)
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.switchTo).toHaveBeenCalledWith(1, true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,100 @@
|
||||
import React from 'react'
|
||||
import {Animated} from 'react-native'
|
||||
import {TabsSelector} from '../../../../src/view/shell/mobile/TabsSelector'
|
||||
import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
|
||||
import {mockedNavigationStore} from '../../../../__mocks__/state-mock'
|
||||
|
||||
describe('TabsSelector', () => {
|
||||
const onCloseMock = jest.fn()
|
||||
|
||||
const mockedProps = {
|
||||
active: true,
|
||||
tabMenuInterp: new Animated.Value(0),
|
||||
onClose: onCloseMock,
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders tabs selector', () => {
|
||||
const {getByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const tabsSelectorView = getByTestId('tabsSelectorView')
|
||||
|
||||
expect(tabsSelectorView).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders nothing if inactive', () => {
|
||||
const {getByTestId} = render(
|
||||
<TabsSelector {...{...mockedProps, active: false}} />,
|
||||
)
|
||||
|
||||
const emptyView = getByTestId('emptyView')
|
||||
|
||||
expect(emptyView).toBeTruthy()
|
||||
})
|
||||
|
||||
// TODO - this throws currently, but the tabs selector isnt being used atm so I just disabled -prf
|
||||
// it('presses share button', () => {
|
||||
// const shareSpy = jest.spyOn(Share, 'share')
|
||||
// const {getByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
// const shareButton = getByTestId('shareButton')
|
||||
// fireEvent.press(shareButton)
|
||||
|
||||
// expect(onCloseMock).toHaveBeenCalled()
|
||||
// expect(shareSpy).toHaveBeenCalledWith({url: 'https://bsky.app/'})
|
||||
// })
|
||||
|
||||
it('presses clone button', () => {
|
||||
const {getByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const cloneButton = getByTestId('cloneButton')
|
||||
fireEvent.press(cloneButton)
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.newTab).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('presses new tab button', () => {
|
||||
const {getByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const newTabButton = getByTestId('newTabButton')
|
||||
fireEvent.press(newTabButton)
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.newTab).toHaveBeenCalledWith('/')
|
||||
})
|
||||
|
||||
it('presses change tab button', () => {
|
||||
const {getAllByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const changeTabButton = getAllByTestId('changeTabButton')
|
||||
fireEvent.press(changeTabButton[0])
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.newTab).toHaveBeenCalledWith('/')
|
||||
})
|
||||
|
||||
it('presses close tab button', () => {
|
||||
const {getAllByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const closeTabButton = getAllByTestId('closeTabButton')
|
||||
fireEvent.press(closeTabButton[0])
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.setActiveTab).toHaveBeenCalledWith(0)
|
||||
})
|
||||
|
||||
it('presses swipes to close the tab', () => {
|
||||
const {getByTestId} = render(<TabsSelector {...mockedProps} />)
|
||||
|
||||
const tabsSwipable = getByTestId('tabsSwipable')
|
||||
fireEvent(tabsSwipable, 'swipeableRightOpen')
|
||||
|
||||
expect(onCloseMock).toHaveBeenCalled()
|
||||
expect(mockedNavigationStore.setActiveTab).toHaveBeenCalledWith(0)
|
||||
})
|
||||
})
|
||||
@@ -1,55 +0,0 @@
|
||||
# To learn about Buck see [Docs](https://buckbuild.com/).
|
||||
# To run your application with Buck:
|
||||
# - install Buck
|
||||
# - `npm start` - to start the packager
|
||||
# - `cd android`
|
||||
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
|
||||
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
|
||||
# - `buck install -r android/app` - compile, install and run application
|
||||
#
|
||||
|
||||
load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
|
||||
|
||||
lib_deps = []
|
||||
|
||||
create_aar_targets(glob(["libs/*.aar"]))
|
||||
|
||||
create_jar_targets(glob(["libs/*.jar"]))
|
||||
|
||||
android_library(
|
||||
name = "all-libs",
|
||||
exported_deps = lib_deps,
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = "app-code",
|
||||
srcs = glob([
|
||||
"src/main/java/**/*.java",
|
||||
]),
|
||||
deps = [
|
||||
":all-libs",
|
||||
":build_config",
|
||||
":res",
|
||||
],
|
||||
)
|
||||
|
||||
android_build_config(
|
||||
name = "build_config",
|
||||
package = "xyz.blueskyweb.app",
|
||||
)
|
||||
|
||||
android_resource(
|
||||
name = "res",
|
||||
package = "xyz.blueskyweb.app",
|
||||
res = "src/main/res",
|
||||
)
|
||||
|
||||
android_binary(
|
||||
name = "app",
|
||||
keystore = "//android/keystores:debug",
|
||||
manifest = "src/main/AndroidManifest.xml",
|
||||
package_type = "debug",
|
||||
deps = [
|
||||
":app-code",
|
||||
],
|
||||
)
|
||||
@@ -1,128 +1,86 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
/**
|
||||
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
|
||||
* and bundleReleaseJsAndAssets).
|
||||
* These basically call `react-native bundle` with the correct arguments during the Android build
|
||||
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
|
||||
* bundle directly from the development server. Below you can see all the possible configurations
|
||||
* and their defaults. If you decide to add a configuration block, make sure to add it before the
|
||||
* `apply from: "../../node_modules/react-native/react.gradle"` line.
|
||||
*
|
||||
* project.ext.react = [
|
||||
* // the name of the generated asset file containing your JS bundle
|
||||
* bundleAssetName: "index.android.bundle",
|
||||
*
|
||||
* // the entry file for bundle generation. If none specified and
|
||||
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
|
||||
* // default. Can be overridden with ENTRY_FILE environment variable.
|
||||
* entryFile: "index.android.js",
|
||||
*
|
||||
* // https://reactnative.dev/docs/performance#enable-the-ram-format
|
||||
* bundleCommand: "ram-bundle",
|
||||
*
|
||||
* // whether to bundle JS and assets in debug mode
|
||||
* bundleInDebug: false,
|
||||
*
|
||||
* // whether to bundle JS and assets in release mode
|
||||
* bundleInRelease: true,
|
||||
*
|
||||
* // whether to bundle JS and assets in another build variant (if configured).
|
||||
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'bundleIn${productFlavor}${buildType}'
|
||||
* // 'bundleIn${buildType}'
|
||||
* // bundleInFreeDebug: true,
|
||||
* // bundleInPaidRelease: true,
|
||||
* // bundleInBeta: true,
|
||||
*
|
||||
* // whether to disable dev mode in custom build variants (by default only disabled in release)
|
||||
* // for example: to disable dev mode in the staging build type (if configured)
|
||||
* devDisabledInStaging: true,
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'devDisabledIn${productFlavor}${buildType}'
|
||||
* // 'devDisabledIn${buildType}'
|
||||
*
|
||||
* // the root of your project, i.e. where "package.json" lives
|
||||
* root: "../../",
|
||||
*
|
||||
* // where to put the JS bundle asset in debug mode
|
||||
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
|
||||
*
|
||||
* // where to put the JS bundle asset in release mode
|
||||
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
|
||||
*
|
||||
* // where to put drawable resources / React Native assets, e.g. the ones you use via
|
||||
* // require('./image.png')), in debug mode
|
||||
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
|
||||
*
|
||||
* // where to put drawable resources / React Native assets, e.g. the ones you use via
|
||||
* // require('./image.png')), in release mode
|
||||
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
|
||||
*
|
||||
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
|
||||
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
|
||||
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
|
||||
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
|
||||
* // for example, you might want to remove it from here.
|
||||
* inputExcludes: ["android/**", "ios/**"],
|
||||
*
|
||||
* // override which node gets called and with what additional arguments
|
||||
* nodeExecutableAndArgs: ["node"],
|
||||
*
|
||||
* // supply additional arguments to the packager
|
||||
* extraPackagerArgs: []
|
||||
* ]
|
||||
* This is the configuration block to customize your React Native Android app.
|
||||
* By default you don't need to apply any configuration, just uncomment the lines you need.
|
||||
*/
|
||||
|
||||
project.ext.react = [
|
||||
enableHermes: false, // clean and rebuild if changing
|
||||
]
|
||||
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
react {
|
||||
/* Folders */
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '..'
|
||||
// root = file("../")
|
||||
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
|
||||
// reactNativeDir = file("../node_modules/react-native")
|
||||
// The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
|
||||
// codegenDir = file("../node_modules/react-native-codegen")
|
||||
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
|
||||
// cliFile = file("../node_modules/react-native/cli.js")
|
||||
/* Variants */
|
||||
// The list of variants to that are debuggable. For those we're going to
|
||||
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
|
||||
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
|
||||
// debuggableVariants = ["liteDebug", "prodDebug"]
|
||||
/* Bundling */
|
||||
// A list containing the node command and its flags. Default is just 'node'.
|
||||
// nodeExecutableAndArgs = ["node"]
|
||||
//
|
||||
// The command to run when bundling. By default is 'bundle'
|
||||
// bundleCommand = "ram-bundle"
|
||||
//
|
||||
// The path to the CLI configuration file. Default is empty.
|
||||
// bundleConfig = file(../rn-cli.config.js)
|
||||
//
|
||||
// The name of the generated asset file containing your JS bundle
|
||||
// bundleAssetName = "MyApplication.android.bundle"
|
||||
//
|
||||
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
|
||||
// entryFile = file("../js/MyApplication.android.js")
|
||||
//
|
||||
// A list of extra flags to pass to the 'bundle' commands.
|
||||
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
|
||||
// extraPackagerArgs = []
|
||||
/* Hermes Commands */
|
||||
// The hermes compiler command to run. By default it is 'hermesc'
|
||||
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
|
||||
//
|
||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||
// hermesFlags = ["-O", "-output-source-map"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
* - An APK that only works on ARM devices
|
||||
* - An APK that only works on x86 devices
|
||||
* The advantage is the size of the APK is reduced by about 4MB.
|
||||
* Upload all the APKs to the Play Store and people will download
|
||||
* the correct one based on the CPU architecture of their device.
|
||||
* Set this to true to create four separate APKs instead of one,
|
||||
* one for each native architecture. This is useful if you don't
|
||||
* use App Bundles (https://developer.android.com/guide/app-bundle/)
|
||||
* and want to have separate APKs to upload to the Play Store.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
|
||||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = false
|
||||
|
||||
/**
|
||||
* The preferred build flavor of JavaScriptCore.
|
||||
* The preferred build flavor of JavaScriptCore (JSC)
|
||||
*
|
||||
* For example, to use the international variant, you can use:
|
||||
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
|
||||
*
|
||||
* The international variant includes ICU i18n library and necessary data
|
||||
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
||||
* give correct results when using with locales other than en-US. Note that
|
||||
* give correct results when using with locales other than en-US. Note that
|
||||
* this variant is about 6MiB larger per architecture than default.
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
|
||||
/**
|
||||
* Whether to enable the Hermes VM.
|
||||
*
|
||||
* This should be set on project.ext.react and that value will be read here. If it is not set
|
||||
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
|
||||
* and the benefits of using Hermes will therefore be sharply reduced.
|
||||
*/
|
||||
def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
|
||||
/**
|
||||
* Architectures to build native code for.
|
||||
* Private function to get the list of Native Architectures you want to build.
|
||||
* This reads the value from reactNativeArchitectures in your gradle.properties
|
||||
* file and works together with the --active-arch-only flag of react-native run-android.
|
||||
*/
|
||||
def reactNativeArchitectures() {
|
||||
def value = project.getProperties().get("reactNativeArchitectures")
|
||||
@@ -134,84 +92,13 @@ android {
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace "xyz.blueskyweb.app"
|
||||
defaultConfig {
|
||||
applicationId "xyz.blueskyweb.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
// We configure the NDK build only if you decide to opt-in for the New Architecture.
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_PLATFORM=android-21",
|
||||
"APP_STL=c++_shared",
|
||||
"NDK_TOOLCHAIN_VERSION=clang",
|
||||
"GENERATED_SRC_DIR=$buildDir/generated/source",
|
||||
"PROJECT_BUILD_DIR=$buildDir",
|
||||
"REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
|
||||
"REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build"
|
||||
cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
|
||||
cppFlags "-std=c++17"
|
||||
// Make sure this target name is the same you specify inside the
|
||||
// src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
|
||||
targets "app_appmodules"
|
||||
|
||||
// Fix for windows limit on number of character in file paths and in command lines
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
arguments "NDK_APP_SHORT_COMMANDS=true"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!enableSeparateBuildPerCPUArchitecture) {
|
||||
ndk {
|
||||
abiFilters (*reactNativeArchitectures())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
// We configure the NDK build only if you decide to opt-in for the New Architecture.
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path "$projectDir/src/main/jni/Android.mk"
|
||||
}
|
||||
}
|
||||
def reactAndroidProjectDir = project(':ReactAndroid').projectDir
|
||||
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
|
||||
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
|
||||
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
|
||||
into("$buildDir/react-ndk/exported")
|
||||
}
|
||||
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
|
||||
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
|
||||
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
|
||||
into("$buildDir/react-ndk/exported")
|
||||
}
|
||||
afterEvaluate {
|
||||
// If you wish to add a custom TurboModule or component locally,
|
||||
// you should uncomment this line.
|
||||
// preBuild.dependsOn("generateCodegenArtifactsFromSchema")
|
||||
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
|
||||
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
|
||||
|
||||
// Due to a bug inside AGP, we have to explicitly set a dependency
|
||||
// between configureNdkBuild* tasks and the preBuild tasks.
|
||||
// This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
|
||||
configureNdkBuildRelease.dependsOn(preReleaseBuild)
|
||||
configureNdkBuildDebug.dependsOn(preDebugBuild)
|
||||
reactNativeArchitectures().each { architecture ->
|
||||
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
|
||||
dependsOn("preDebugBuild")
|
||||
}
|
||||
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
|
||||
dependsOn("preReleaseBuild")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
splits {
|
||||
@@ -261,60 +148,24 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.fbjni'
|
||||
}
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
|
||||
|
||||
implementation project(':rn-fetch-blob')
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
|
||||
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.flipper'
|
||||
exclude group:'com.squareup.okhttp3', module:'okhttp'
|
||||
}
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.flipper'
|
||||
}
|
||||
|
||||
if (enableHermes) {
|
||||
def hermesPath = "../../node_modules/hermes-engine/android/";
|
||||
debugImplementation files(hermesPath + "hermes-debug.aar")
|
||||
releaseImplementation files(hermesPath + "hermes-release.aar")
|
||||
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
|
||||
if (hermesEnabled.toBoolean()) {
|
||||
implementation("com.facebook.react:hermes-android")
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
// If new architecture is enabled, we let you build RN from source
|
||||
// Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
|
||||
// This will be applied to all the imported transtitive dependency.
|
||||
configurations.all {
|
||||
resolutionStrategy.dependencySubstitution {
|
||||
substitute(module("com.facebook.react:react-native"))
|
||||
.using(project(":ReactAndroid")).because("On New Architecture we're building React Native from source")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
task copyDownloadableDepsToLibs(type: Copy) {
|
||||
from configurations.implementation
|
||||
into 'libs'
|
||||
}
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
|
||||
def isNewArchitectureEnabled() {
|
||||
// To opt-in for the New Architecture, you can either:
|
||||
// - Set `newArchEnabled` to true inside the `gradle.properties` file
|
||||
// - Invoke gradle with `-newArchEnabled=true`
|
||||
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
|
||||
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
"""Helper definitions to glob .aar and .jar targets"""
|
||||
|
||||
def create_aar_targets(aarfiles):
|
||||
for aarfile in aarfiles:
|
||||
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
|
||||
lib_deps.append(":" + name)
|
||||
android_prebuilt_aar(
|
||||
name = name,
|
||||
aar = aarfile,
|
||||
)
|
||||
|
||||
def create_jar_targets(jarfiles):
|
||||
for jarfile in jarfiles:
|
||||
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
|
||||
lib_deps.append(":" + name)
|
||||
prebuilt_jar(
|
||||
name = name,
|
||||
binary_jar = jarfile,
|
||||
)
|
||||
@@ -25,13 +25,16 @@ import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.network.NetworkingModule;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* Class responsible of loading Flipper inside your React Native application. This is the debug
|
||||
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
|
||||
*/
|
||||
public class ReactNativeFlipper {
|
||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (FlipperUtils.shouldEnableFlipper(context)) {
|
||||
final FlipperClient client = AndroidFlipperClient.getInstance(context);
|
||||
|
||||
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
|
||||
client.addPlugin(new ReactFlipperPlugin());
|
||||
client.addPlugin(new DatabasesFlipperPlugin(context));
|
||||
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
package="xyz.blueskyweb.app">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
@@ -15,7 +18,7 @@
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -2,7 +2,8 @@ package xyz.blueskyweb.app;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
@@ -17,30 +18,19 @@ public class MainActivity extends ReactActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
|
||||
* you can specify the rendered you wish to use (Fabric or the older renderer).
|
||||
* Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
|
||||
* DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
|
||||
* (aka React 18) with two boolean flags.
|
||||
*/
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new MainActivityDelegate(this, getMainComponentName());
|
||||
}
|
||||
|
||||
public static class MainActivityDelegate extends ReactActivityDelegate {
|
||||
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
|
||||
super(activity, mainComponentName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactRootView createRootView() {
|
||||
ReactRootView reactRootView = new ReactRootView(getContext());
|
||||
return new DefaultReactActivityDelegate(
|
||||
this,
|
||||
getMainComponentName(),
|
||||
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
|
||||
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
|
||||
return reactRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(null);
|
||||
}
|
||||
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
|
||||
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
|
||||
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package xyz.blueskyweb.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import xyz.blueskyweb.app.newarchitecture.MainApplicationReactNativeHost;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -16,7 +15,7 @@ import java.util.List;
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new ReactNativeHost(this) {
|
||||
new DefaultReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
@@ -35,18 +34,20 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
};
|
||||
|
||||
private final ReactNativeHost mNewArchitectureNativeHost =
|
||||
new MainApplicationReactNativeHost(this);
|
||||
@Override
|
||||
protected boolean isNewArchEnabled() {
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
@Override
|
||||
protected Boolean isHermesEnabled() {
|
||||
return BuildConfig.IS_HERMES_ENABLED;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
return mNewArchitectureNativeHost;
|
||||
} else {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,37 +56,10 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
// If you opted-in for the New Architecture, we enable the TurboModule system
|
||||
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
|
||||
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
*
|
||||
* @param context
|
||||
* @param reactInstanceManager
|
||||
*/
|
||||
private static void initializeFlipper(
|
||||
Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
try {
|
||||
/*
|
||||
We use reflection here to pick up the class that initializes Flipper,
|
||||
since Flipper library is not available in release mode
|
||||
*/
|
||||
Class<?> aClass = Class.forName("com.app.ReactNativeFlipper");
|
||||
aClass
|
||||
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
|
||||
.invoke(null, context, reactInstanceManager);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
DefaultNewArchitectureEntryPoint.load();
|
||||
}
|
||||
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
package xyz.blueskyweb.app.newarchitecture;
|
||||
|
||||
import android.app.Application;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
|
||||
import com.facebook.react.bridge.JSIModulePackage;
|
||||
import com.facebook.react.bridge.JSIModuleProvider;
|
||||
import com.facebook.react.bridge.JSIModuleSpec;
|
||||
import com.facebook.react.bridge.JSIModuleType;
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.UIManager;
|
||||
import com.facebook.react.fabric.ComponentFactory;
|
||||
import com.facebook.react.fabric.CoreComponentsRegistry;
|
||||
import com.facebook.react.fabric.EmptyReactNativeConfig;
|
||||
import com.facebook.react.fabric.FabricJSIModuleProvider;
|
||||
import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||
import xyz.blueskyweb.app.BuildConfig;
|
||||
import xyz.blueskyweb.app.newarchitecture.components.MainComponentsRegistry;
|
||||
import xyz.blueskyweb.app.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
|
||||
* TurboModule delegates and the Fabric Renderer.
|
||||
*
|
||||
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
|
||||
* `newArchEnabled` property). Is ignored otherwise.
|
||||
*/
|
||||
public class MainApplicationReactNativeHost extends ReactNativeHost {
|
||||
public MainApplicationReactNativeHost(Application application) {
|
||||
super(application);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
|
||||
// packages.add(new TurboReactPackage() { ... });
|
||||
// If you have custom Fabric Components, their ViewManagers should also be loaded here
|
||||
// inside a ReactPackage.
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected ReactPackageTurboModuleManagerDelegate.Builder
|
||||
getReactPackageTurboModuleManagerDelegateBuilder() {
|
||||
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
|
||||
// for the new architecture and to use TurboModules correctly.
|
||||
return new MainApplicationTurboModuleManagerDelegate.Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSIModulePackage getJSIModulePackage() {
|
||||
return new JSIModulePackage() {
|
||||
@Override
|
||||
public List<JSIModuleSpec> getJSIModules(
|
||||
final ReactApplicationContext reactApplicationContext,
|
||||
final JavaScriptContextHolder jsContext) {
|
||||
final List<JSIModuleSpec> specs = new ArrayList<>();
|
||||
|
||||
// Here we provide a new JSIModuleSpec that will be responsible of providing the
|
||||
// custom Fabric Components.
|
||||
specs.add(
|
||||
new JSIModuleSpec() {
|
||||
@Override
|
||||
public JSIModuleType getJSIModuleType() {
|
||||
return JSIModuleType.UIManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
|
||||
final ComponentFactory componentFactory = new ComponentFactory();
|
||||
CoreComponentsRegistry.register(componentFactory);
|
||||
|
||||
// Here we register a Components Registry.
|
||||
// The one that is generated with the template contains no components
|
||||
// and just provides you the one from React Native core.
|
||||
MainComponentsRegistry.register(componentFactory);
|
||||
|
||||
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
|
||||
|
||||
ViewManagerRegistry viewManagerRegistry =
|
||||
new ViewManagerRegistry(
|
||||
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
|
||||
|
||||
return new FabricJSIModuleProvider(
|
||||
reactApplicationContext,
|
||||
componentFactory,
|
||||
new EmptyReactNativeConfig(),
|
||||
viewManagerRegistry);
|
||||
}
|
||||
});
|
||||
return specs;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package xyz.blueskyweb.app.newarchitecture.components;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.fabric.ComponentFactory;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* Class responsible to load the custom Fabric Components. This class has native methods and needs a
|
||||
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
|
||||
* folder for you).
|
||||
*
|
||||
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
|
||||
* `newArchEnabled` property). Is ignored otherwise.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class MainComponentsRegistry {
|
||||
static {
|
||||
SoLoader.loadLibrary("fabricjni");
|
||||
}
|
||||
|
||||
@DoNotStrip private final HybridData mHybridData;
|
||||
|
||||
@DoNotStrip
|
||||
private native HybridData initHybrid(ComponentFactory componentFactory);
|
||||
|
||||
@DoNotStrip
|
||||
private MainComponentsRegistry(ComponentFactory componentFactory) {
|
||||
mHybridData = initHybrid(componentFactory);
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public static MainComponentsRegistry register(ComponentFactory componentFactory) {
|
||||
return new MainComponentsRegistry(componentFactory);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package xyz.blueskyweb.app.newarchitecture.modules;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible to load the TurboModules. This class has native methods and needs a
|
||||
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
|
||||
* folder for you).
|
||||
*
|
||||
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
|
||||
* `newArchEnabled` property). Is ignored otherwise.
|
||||
*/
|
||||
public class MainApplicationTurboModuleManagerDelegate
|
||||
extends ReactPackageTurboModuleManagerDelegate {
|
||||
|
||||
private static volatile boolean sIsSoLibraryLoaded;
|
||||
|
||||
protected MainApplicationTurboModuleManagerDelegate(
|
||||
ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
|
||||
super(reactApplicationContext, packages);
|
||||
}
|
||||
|
||||
protected native HybridData initHybrid();
|
||||
|
||||
native boolean canCreateTurboModule(String moduleName);
|
||||
|
||||
public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
|
||||
protected MainApplicationTurboModuleManagerDelegate build(
|
||||
ReactApplicationContext context, List<ReactPackage> packages) {
|
||||
return new MainApplicationTurboModuleManagerDelegate(context, packages);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void maybeLoadOtherSoLibraries() {
|
||||
if (!sIsSoLibraryLoaded) {
|
||||
// If you change the name of your application .so file in the Android.mk file,
|
||||
// make sure you update the name here as well.
|
||||
SoLoader.loadLibrary("app_appmodules");
|
||||
sIsSoLibraryLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#include "MainApplicationModuleProvider.h"
|
||||
|
||||
#include <rncore.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
|
||||
const std::string moduleName,
|
||||
const JavaTurboModule::InitParams ¶ms) {
|
||||
// Here you can provide your own module provider for TurboModules coming from
|
||||
// either your application or from external libraries. The approach to follow
|
||||
// is similar to the following (for a library called `samplelibrary`:
|
||||
//
|
||||
// auto module = samplelibrary_ModuleProvider(moduleName, params);
|
||||
// if (module != nullptr) {
|
||||
// return module;
|
||||
// }
|
||||
// return rncore_ModuleProvider(moduleName, params);
|
||||
return rncore_ModuleProvider(moduleName, params);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <ReactCommon/JavaTurboModule.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
|
||||
const std::string moduleName,
|
||||
const JavaTurboModule::InitParams ¶ms);
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "MainApplicationTurboModuleManagerDelegate.h"
|
||||
#include "MainApplicationModuleProvider.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
jni::local_ref<MainApplicationTurboModuleManagerDelegate::jhybriddata>
|
||||
MainApplicationTurboModuleManagerDelegate::initHybrid(
|
||||
jni::alias_ref<jhybridobject>) {
|
||||
return makeCxxInstance();
|
||||
}
|
||||
|
||||
void MainApplicationTurboModuleManagerDelegate::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod(
|
||||
"initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
|
||||
makeNativeMethod(
|
||||
"canCreateTurboModule",
|
||||
MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule>
|
||||
MainApplicationTurboModuleManagerDelegate::getTurboModule(
|
||||
const std::string name,
|
||||
const std::shared_ptr<CallInvoker> jsInvoker) {
|
||||
// Not implemented yet: provide pure-C++ NativeModules here.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule>
|
||||
MainApplicationTurboModuleManagerDelegate::getTurboModule(
|
||||
const std::string name,
|
||||
const JavaTurboModule::InitParams ¶ms) {
|
||||
return MainApplicationModuleProvider(name, params);
|
||||
}
|
||||
|
||||
bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
|
||||
std::string name) {
|
||||
return getTurboModule(name, nullptr) != nullptr ||
|
||||
getTurboModule(name, {.moduleName = name}) != nullptr;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,38 +0,0 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <ReactCommon/TurboModuleManagerDelegate.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class MainApplicationTurboModuleManagerDelegate
|
||||
: public jni::HybridClass<
|
||||
MainApplicationTurboModuleManagerDelegate,
|
||||
TurboModuleManagerDelegate> {
|
||||
public:
|
||||
// Adapt it to the package you used for your Java class.
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/app/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>);
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
std::shared_ptr<TurboModule> getTurboModule(
|
||||
const std::string name,
|
||||
const std::shared_ptr<CallInvoker> jsInvoker) override;
|
||||
std::shared_ptr<TurboModule> getTurboModule(
|
||||
const std::string name,
|
||||
const JavaTurboModule::InitParams ¶ms) override;
|
||||
|
||||
/**
|
||||
* Test-only method. Allows user to verify whether a TurboModule can be
|
||||
* created by instances of this class.
|
||||
*/
|
||||
bool canCreateTurboModule(std::string name);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "MainComponentsRegistry.h"
|
||||
|
||||
#include <CoreComponentsRegistry.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/renderer/components/rncore/ComponentDescriptors.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
|
||||
|
||||
std::shared_ptr<ComponentDescriptorProviderRegistry const>
|
||||
MainComponentsRegistry::sharedProviderRegistry() {
|
||||
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
|
||||
|
||||
// Custom Fabric Components go here. You can register custom
|
||||
// components coming from your App or from 3rd party libraries here.
|
||||
//
|
||||
// providerRegistry->add(concreteComponentDescriptorProvider<
|
||||
// AocViewerComponentDescriptor>());
|
||||
return providerRegistry;
|
||||
}
|
||||
|
||||
jni::local_ref<MainComponentsRegistry::jhybriddata>
|
||||
MainComponentsRegistry::initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
ComponentFactory *delegate) {
|
||||
auto instance = makeCxxInstance(delegate);
|
||||
|
||||
auto buildRegistryFunction =
|
||||
[](EventDispatcher::Weak const &eventDispatcher,
|
||||
ContextContainer::Shared const &contextContainer)
|
||||
-> ComponentDescriptorRegistry::Shared {
|
||||
auto registry = MainComponentsRegistry::sharedProviderRegistry()
|
||||
->createComponentDescriptorRegistry(
|
||||
{eventDispatcher, contextContainer});
|
||||
|
||||
auto mutableRegistry =
|
||||
std::const_pointer_cast<ComponentDescriptorRegistry>(registry);
|
||||
|
||||
mutableRegistry->setFallbackComponentDescriptor(
|
||||
std::make_shared<UnimplementedNativeViewComponentDescriptor>(
|
||||
ComponentDescriptorParameters{
|
||||
eventDispatcher, contextContainer, nullptr}));
|
||||
|
||||
return registry;
|
||||
};
|
||||
|
||||
delegate->buildRegistryFunction = buildRegistryFunction;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void MainComponentsRegistry::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <ComponentFactory.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class MainComponentsRegistry
|
||||
: public facebook::jni::HybridClass<MainComponentsRegistry> {
|
||||
public:
|
||||
// Adapt it to the package you used for your Java class.
|
||||
constexpr static auto kJavaDescriptor =
|
||||
"Lcom/app/newarchitecture/components/MainComponentsRegistry;";
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
MainComponentsRegistry(ComponentFactory *delegate);
|
||||
|
||||
private:
|
||||
static std::shared_ptr<ComponentDescriptorProviderRegistry const>
|
||||
sharedProviderRegistry();
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
ComponentFactory *delegate);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <fbjni/fbjni.h>
|
||||
#include "MainApplicationTurboModuleManagerDelegate.h"
|
||||
#include "MainComponentsRegistry.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
facebook::react::MainApplicationTurboModuleManagerDelegate::
|
||||
registerNatives();
|
||||
facebook::react::MainComponentsRegistry::registerNatives();
|
||||
});
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||
* directory of this source tree.
|
||||
*/
|
||||
package xyz.blueskyweb.app;
|
||||
import android.content.Context;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
/**
|
||||
* Class responsible of loading Flipper inside your React Native application. This is the release
|
||||
* flavor of it so it's empty as we don't want to load Flipper.
|
||||
*/
|
||||
public class ReactNativeFlipper {
|
||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
// Do nothing as we don't want to initialize Flipper on Release.
|
||||
}
|
||||
}
|
||||
@@ -4,50 +4,20 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "31.0.0"
|
||||
buildToolsVersion = "33.0.0"
|
||||
minSdkVersion = 21
|
||||
compileSdkVersion = 31
|
||||
targetSdkVersion = 31
|
||||
compileSdkVersion = 33
|
||||
targetSdkVersion = 33
|
||||
|
||||
if (System.properties['os.arch'] == "aarch64") {
|
||||
// For M1 Users we need to use the NDK 24 which added support for aarch64
|
||||
ndkVersion = "24.0.8215888"
|
||||
} else {
|
||||
// Otherwise we default to the side-by-side NDK version from AGP.
|
||||
ndkVersion = "21.4.7075529"
|
||||
}
|
||||
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
|
||||
ndkVersion = "23.1.7779620"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath('com.android.tools.build:gradle:7.2.1')
|
||||
classpath("com.android.tools.build:gradle:7.3.1")
|
||||
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||
classpath("de.undercouch:gradle-download-task:4.1.2")
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url("$rootDir/../node_modules/react-native/android")
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url("$rootDir/../node_modules/jsc-android/dist")
|
||||
}
|
||||
mavenCentral {
|
||||
// We don't want to fetch react-native from Maven Central as there are
|
||||
// older versions over there.
|
||||
content {
|
||||
excludeGroup "com.facebook.react"
|
||||
}
|
||||
}
|
||||
google()
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,3 +38,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
|
||||
# Use this property to enable or disable the Hermes JS engine.
|
||||
# If set to false, you will be using JSC instead.
|
||||
hermesEnabled=true
|
||||
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -2,8 +2,5 @@ rootProject.name = 'app'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
includeBuild('../node_modules/react-native-gradle-plugin')
|
||||
|
||||
if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
|
||||
include(":ReactAndroid")
|
||||
project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
|
||||
}
|
||||
include ':rn-fetch-blob'
|
||||
project(':rn-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/rn-fetch-blob/android')
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# This `.xcode.env` file is versioned and is used to source the environment
|
||||
# used when running script phases inside Xcode.
|
||||
# To customize your local environment, you can create an `.xcode.env.local`
|
||||
# file that is not versioned.
|
||||
# NODE_BINARY variable contains the PATH to the node executable.
|
||||
#
|
||||
# Customize the NODE_BINARY variable here.
|
||||
# For example, to use nvm with brew, add the following line
|
||||
# . "$(brew --prefix nvm)/nvm.sh" --no-use
|
||||
export NODE_BINARY=$(command -v node)
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
|
||||
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||
@@ -9,33 +9,33 @@
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<scene sceneID="s0d-6b-0kx">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" image="LaunchScreen" translatesAutoresizingMaskIntoConstraints="NO" id="3xW-LZ-8bI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" image="LaunchScreen" translatesAutoresizingMaskIntoConstraints="NO" id="Ppr-Vi-7AA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="3xW-LZ-8bI" secondAttribute="bottom" id="Qjl-JH-apV"/>
|
||||
<constraint firstItem="3xW-LZ-8bI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="c7a-bI-Hl7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="3xW-LZ-8bI" secondAttribute="trailing" id="vM9-Qy-zds"/>
|
||||
<constraint firstItem="3xW-LZ-8bI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="yhO-am-Ve0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Ppr-Vi-7AA" secondAttribute="trailing" id="8NR-sO-ZhN"/>
|
||||
<constraint firstItem="Ppr-Vi-7AA" firstAttribute="top" secondItem="5EZ-qb-Rvc" secondAttribute="top" id="Od5-pK-zM2"/>
|
||||
<constraint firstItem="Ppr-Vi-7AA" firstAttribute="leading" secondItem="5EZ-qb-Rvc" secondAttribute="leading" id="Ww6-nx-IYo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Ppr-Vi-7AA" secondAttribute="bottom" id="vTP-N3-Ihm"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||
<point key="canvasLocation" x="119.84732824427481" y="4.9295774647887329"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LaunchScreen" width="500" height="750"/>
|
||||
<image name="LaunchScreen" width="600" height="900"/>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
@@ -1,8 +1,25 @@
|
||||
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
||||
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
||||
|
||||
platform :ios, '11.0'
|
||||
install! 'cocoapods', :deterministic_uuids => false
|
||||
platform :ios, min_ios_version_supported
|
||||
prepare_react_native_project!
|
||||
|
||||
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
|
||||
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
|
||||
#
|
||||
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
|
||||
# ```js
|
||||
# module.exports = {
|
||||
# dependencies: {
|
||||
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
|
||||
# ```
|
||||
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
|
||||
|
||||
linkage = ENV['USE_FRAMEWORKS']
|
||||
if linkage != nil
|
||||
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
|
||||
use_frameworks! :linkage => linkage.to_sym
|
||||
end
|
||||
|
||||
target 'app' do
|
||||
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
|
||||
@@ -13,9 +30,16 @@ target 'app' do
|
||||
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
# to enable hermes on iOS, change `false` to `true` and then install pods
|
||||
# Hermes is now enabled by default. Disable by setting this flag to false.
|
||||
# Upcoming versions of React Native may rely on get_default_flags(), but
|
||||
# we make it explicit here to aid in the React Native upgrade process.
|
||||
:hermes_enabled => flags[:hermes_enabled],
|
||||
:fabric_enabled => flags[:fabric_enabled],
|
||||
# Enables Flipper.
|
||||
#
|
||||
# Note that if you have use_frameworks! enabled, Flipper will not work and
|
||||
# you should disable the next line.
|
||||
#:flipper_configuration => flipper_config,
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||
)
|
||||
@@ -25,14 +49,24 @@ target 'app' do
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
# Enables Flipper.
|
||||
#
|
||||
# Note that if you have use_frameworks! enabled, Flipper will not work and
|
||||
# you should disable the next line.
|
||||
#use_flipper!()
|
||||
|
||||
post_install do |installer|
|
||||
react_native_post_install(installer)
|
||||
# Temporary fix until CocoaPods 1.12.0 is released.
|
||||
# https://github.com/CocoaPods/CocoaPods/issues/11402#issuecomment-1201464693
|
||||
installer.pods_project.targets.each do |target|
|
||||
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
react_native_post_install(
|
||||
installer,
|
||||
# Set `mac_catalyst_enabled` to `true` in order to apply patches
|
||||
# necessary for Mac Catalyst builds
|
||||
:mac_catalyst_enabled => false
|
||||
)
|
||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||
|
||||
# iOS fix
|
||||
|
||||
@@ -3,227 +3,250 @@ PODS:
|
||||
- BVLinearGradient (2.6.2):
|
||||
- React-Core
|
||||
- DoubleConversion (1.1.6)
|
||||
- FBLazyVector (0.68.2)
|
||||
- FBReactNativeSpec (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Core (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- FBLazyVector (0.71.1)
|
||||
- FBReactNativeSpec (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Core (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- fmt (6.2.1)
|
||||
- glog (0.3.5)
|
||||
- RCT-Folly (2021.06.28.00-v2):
|
||||
- hermes-engine (0.71.0):
|
||||
- hermes-engine/Pre-built (= 0.71.0)
|
||||
- hermes-engine/Pre-built (0.71.0)
|
||||
- libevent (2.1.12)
|
||||
- RCT-Folly (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Default (= 2021.06.28.00-v2)
|
||||
- RCT-Folly/Default (2021.06.28.00-v2):
|
||||
- RCT-Folly/Default (= 2021.07.22.00)
|
||||
- RCT-Folly/Default (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCTRequired (0.68.2)
|
||||
- RCTTypeSafety (0.68.2):
|
||||
- FBLazyVector (= 0.68.2)
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.2)
|
||||
- React-Core (= 0.68.2)
|
||||
- React (0.68.2):
|
||||
- React-Core (= 0.68.2)
|
||||
- React-Core/DevSupport (= 0.68.2)
|
||||
- React-Core/RCTWebSocket (= 0.68.2)
|
||||
- React-RCTActionSheet (= 0.68.2)
|
||||
- React-RCTAnimation (= 0.68.2)
|
||||
- React-RCTBlob (= 0.68.2)
|
||||
- React-RCTImage (= 0.68.2)
|
||||
- React-RCTLinking (= 0.68.2)
|
||||
- React-RCTNetwork (= 0.68.2)
|
||||
- React-RCTSettings (= 0.68.2)
|
||||
- React-RCTText (= 0.68.2)
|
||||
- React-RCTVibration (= 0.68.2)
|
||||
- React-callinvoker (0.68.2)
|
||||
- React-Codegen (0.68.2):
|
||||
- FBReactNativeSpec (= 0.68.2)
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Core (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-Core (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/Default (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.2)
|
||||
- React-Core/RCTWebSocket (= 0.68.2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-jsinspector (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.68.2):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsiexecutor (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- Yoga
|
||||
- React-CoreModules (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/CoreModulesHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-RCTImage (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-cxxreact (0.68.2):
|
||||
- boost (= 1.76.0)
|
||||
- RCT-Folly/Futures (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-callinvoker (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-jsinspector (= 0.68.2)
|
||||
- React-logger (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- React-runtimeexecutor (= 0.68.2)
|
||||
- React-jsi (0.68.2):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsi/Default (= 0.68.2)
|
||||
- React-jsi/Default (0.68.2):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsiexecutor (0.68.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- React-jsinspector (0.68.2)
|
||||
- React-logger (0.68.2):
|
||||
- glog
|
||||
- react-native-cameraroll (5.1.0):
|
||||
- libevent
|
||||
- RCTRequired (0.71.1)
|
||||
- RCTTypeSafety (0.71.1):
|
||||
- FBLazyVector (= 0.71.1)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- React-Core (= 0.71.1)
|
||||
- React (0.71.1):
|
||||
- React-Core (= 0.71.1)
|
||||
- React-Core/DevSupport (= 0.71.1)
|
||||
- React-Core/RCTWebSocket (= 0.71.1)
|
||||
- React-RCTActionSheet (= 0.71.1)
|
||||
- React-RCTAnimation (= 0.71.1)
|
||||
- React-RCTBlob (= 0.71.1)
|
||||
- React-RCTImage (= 0.71.1)
|
||||
- React-RCTLinking (= 0.71.1)
|
||||
- React-RCTNetwork (= 0.71.1)
|
||||
- React-RCTSettings (= 0.71.1)
|
||||
- React-RCTText (= 0.71.1)
|
||||
- React-RCTVibration (= 0.71.1)
|
||||
- React-callinvoker (0.71.1)
|
||||
- React-Codegen (0.71.1):
|
||||
- FBReactNativeSpec
|
||||
- hermes-engine
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- react-native-pager-view (6.0.2):
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-Core (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.1)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/Default (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.1)
|
||||
- React-Core/RCTWebSocket (= 0.71.1)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-jsinspector (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.71.1):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.1)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- Yoga
|
||||
- React-CoreModules (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/CoreModulesHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-RCTImage (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-cxxreact (0.71.1):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsinspector (= 0.71.1)
|
||||
- React-logger (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- React-runtimeexecutor (= 0.71.1)
|
||||
- React-hermes (0.71.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCT-Folly/Futures (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-jsinspector (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- React-jsi (0.71.1):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsiexecutor (0.71.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- React-jsinspector (0.71.1)
|
||||
- React-logger (0.71.1):
|
||||
- glog
|
||||
- react-native-blur (4.3.0):
|
||||
- React-Core
|
||||
- react-native-cameraroll (5.2.2):
|
||||
- React-Core
|
||||
- react-native-image-resizer (3.0.4):
|
||||
- React-Core
|
||||
- react-native-pager-view (6.1.2):
|
||||
- React-Core
|
||||
- react-native-paste-input (0.6.0):
|
||||
- React-Core
|
||||
- Swime (= 3.0.6)
|
||||
- react-native-safe-area-context (4.4.1):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
@@ -234,76 +257,98 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-version-number (0.3.6):
|
||||
- React
|
||||
- React-perflogger (0.68.2)
|
||||
- React-RCTActionSheet (0.68.2):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.68.2)
|
||||
- React-RCTAnimation (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTAnimationHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTBlob (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTBlobHeaders (= 0.68.2)
|
||||
- React-Core/RCTWebSocket (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-RCTNetwork (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTImage (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTImageHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-RCTNetwork (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTLinking (0.68.2):
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTLinkingHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTNetwork (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTNetworkHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTSettings (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTSettingsHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-RCTText (0.68.2):
|
||||
- React-Core/RCTTextHeaders (= 0.68.2)
|
||||
- React-RCTVibration (0.68.2):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.68.2)
|
||||
- React-Core/RCTVibrationHeaders (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (= 0.68.2)
|
||||
- React-runtimeexecutor (0.68.2):
|
||||
- React-jsi (= 0.68.2)
|
||||
- ReactCommon/turbomodule/core (0.68.2):
|
||||
- React-perflogger (0.71.1)
|
||||
- React-RCTActionSheet (0.71.1):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.71.1)
|
||||
- React-RCTAnimation (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTAnimationHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTAppDelegate (0.71.1):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-RCTBlob (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTBlobHeaders (= 0.71.1)
|
||||
- React-Core/RCTWebSocket (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-RCTNetwork (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTImage (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTImageHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-RCTNetwork (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTLinking (0.71.1):
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTLinkingHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTNetwork (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTNetworkHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTSettings (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTSettingsHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTText (0.71.1):
|
||||
- React-Core/RCTTextHeaders (= 0.71.1)
|
||||
- React-RCTVibration (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.71.1)
|
||||
- React-Core/RCTVibrationHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-runtimeexecutor (0.71.1):
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/bridging (0.71.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-callinvoker (= 0.68.2)
|
||||
- React-Core (= 0.68.2)
|
||||
- React-cxxreact (= 0.68.2)
|
||||
- React-jsi (= 0.68.2)
|
||||
- React-logger (= 0.68.2)
|
||||
- React-perflogger (= 0.68.2)
|
||||
- RNCAsyncStorage (1.17.10):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.1)
|
||||
- React-Core (= 0.71.1)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-logger (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (0.71.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.1)
|
||||
- React-Core (= 0.71.1)
|
||||
- React-cxxreact (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-logger (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNBackgroundFetch (4.1.8):
|
||||
- React-Core
|
||||
- RNCAsyncStorage (1.17.11):
|
||||
- React-Core
|
||||
- RNCClipboard (1.11.1):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.6.1):
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.8.0):
|
||||
- React-Core
|
||||
- RNImageCropPicker (0.38.1):
|
||||
- React-Core
|
||||
@@ -316,7 +361,14 @@ PODS:
|
||||
- TOCropViewController
|
||||
- RNInAppBrowser (3.7.0):
|
||||
- React-Core
|
||||
- RNReanimated (2.10.0):
|
||||
- RNNotifee (7.4.0):
|
||||
- React-Core
|
||||
- RNNotifee/NotifeeCore (= 7.4.0)
|
||||
- RNNotifee/NotifeeCore (7.4.0):
|
||||
- React-Core
|
||||
- RNReactNativeHapticFeedback (1.14.0):
|
||||
- React-Core
|
||||
- RNReanimated (2.13.0):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
@@ -343,11 +395,17 @@ PODS:
|
||||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNScreens (3.17.0):
|
||||
- RNScreens (3.18.2):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNSVG (12.4.4):
|
||||
- RNSVG (12.5.0):
|
||||
- React-Core
|
||||
- segment-analytics-react-native (2.10.1):
|
||||
- React-Core
|
||||
- sovran-react-native
|
||||
- sovran-react-native (0.4.5):
|
||||
- React-Core
|
||||
- Swime (3.0.6)
|
||||
- TOCropViewController (2.6.1)
|
||||
- Yoga (1.14.0)
|
||||
|
||||
@@ -358,6 +416,8 @@ DEPENDENCIES:
|
||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
||||
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
||||
- libevent (~> 2.1.12)
|
||||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
|
||||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
|
||||
@@ -365,22 +425,26 @@ DEPENDENCIES:
|
||||
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
|
||||
- React-Codegen (from `build/generated/ios`)
|
||||
- React-Core (from `../node_modules/react-native/`)
|
||||
- React-Core/DevSupport (from `../node_modules/react-native/`)
|
||||
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
|
||||
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
|
||||
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
|
||||
- React-hermes (from `../node_modules/react-native/ReactCommon/hermes`)
|
||||
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
||||
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
|
||||
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
|
||||
- "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)"
|
||||
- "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)"
|
||||
- react-native-pager-view (from `../node_modules/react-native-pager-view`)
|
||||
- "react-native-paste-input (from `../node_modules/@mattermost/react-native-paste-input`)"
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||
- react-native-version-number (from `../node_modules/react-native-version-number`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
|
||||
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
|
||||
- React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`)
|
||||
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
|
||||
- React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
|
||||
- React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
|
||||
@@ -390,19 +454,28 @@ DEPENDENCIES:
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- rn-fetch-blob (from `../node_modules/rn-fetch-blob`)
|
||||
- RNBackgroundFetch (from `../node_modules/react-native-background-fetch`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
|
||||
- "RNNotifee (from `../node_modules/@notifee/react-native`)"
|
||||
- RNReactNativeHapticFeedback (from `../node_modules/react-native-haptic-feedback`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- "segment-analytics-react-native (from `../node_modules/@segment/analytics-react-native`)"
|
||||
- "sovran-react-native (from `../node_modules/@segment/sovran-react-native`)"
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- fmt
|
||||
- libevent
|
||||
- Swime
|
||||
- TOCropViewController
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
@@ -418,6 +491,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/React/FBReactNativeSpec"
|
||||
glog:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
hermes-engine:
|
||||
:podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
|
||||
RCT-Folly:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
|
||||
RCTRequired:
|
||||
@@ -436,6 +511,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/React/CoreModules"
|
||||
React-cxxreact:
|
||||
:path: "../node_modules/react-native/ReactCommon/cxxreact"
|
||||
React-hermes:
|
||||
:path: "../node_modules/react-native/ReactCommon/hermes"
|
||||
React-jsi:
|
||||
:path: "../node_modules/react-native/ReactCommon/jsi"
|
||||
React-jsiexecutor:
|
||||
@@ -444,10 +521,16 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/jsinspector"
|
||||
React-logger:
|
||||
:path: "../node_modules/react-native/ReactCommon/logger"
|
||||
react-native-blur:
|
||||
:path: "../node_modules/@react-native-community/blur"
|
||||
react-native-cameraroll:
|
||||
:path: "../node_modules/@react-native-camera-roll/camera-roll"
|
||||
react-native-image-resizer:
|
||||
:path: "../node_modules/@bam.tech/react-native-image-resizer"
|
||||
react-native-pager-view:
|
||||
:path: "../node_modules/react-native-pager-view"
|
||||
react-native-paste-input:
|
||||
:path: "../node_modules/@mattermost/react-native-paste-input"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-splash-screen:
|
||||
@@ -460,6 +543,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
|
||||
React-RCTAnimation:
|
||||
:path: "../node_modules/react-native/Libraries/NativeAnimation"
|
||||
React-RCTAppDelegate:
|
||||
:path: "../node_modules/react-native/Libraries/AppDelegate"
|
||||
React-RCTBlob:
|
||||
:path: "../node_modules/react-native/Libraries/Blob"
|
||||
React-RCTImage:
|
||||
@@ -478,22 +563,36 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
rn-fetch-blob:
|
||||
:path: "../node_modules/rn-fetch-blob"
|
||||
RNBackgroundFetch:
|
||||
:path: "../node_modules/react-native-background-fetch"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||
RNCClipboard:
|
||||
:path: "../node_modules/@react-native-clipboard/clipboard"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNImageCropPicker:
|
||||
:path: "../node_modules/react-native-image-crop-picker"
|
||||
RNInAppBrowser:
|
||||
:path: "../node_modules/react-native-inappbrowser-reborn"
|
||||
RNNotifee:
|
||||
:path: "../node_modules/@notifee/react-native"
|
||||
RNReactNativeHapticFeedback:
|
||||
:path: "../node_modules/react-native-haptic-feedback"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNScreens:
|
||||
:path: "../node_modules/react-native-screens"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
segment-analytics-react-native:
|
||||
:path: "../node_modules/@segment/analytics-react-native"
|
||||
sovran-react-native:
|
||||
:path: "../node_modules/@segment/sovran-react-native"
|
||||
Yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
@@ -501,51 +600,66 @@ SPEC CHECKSUMS:
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
|
||||
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
||||
FBLazyVector: a7a655862f6b09625d11c772296b01cd5164b648
|
||||
FBReactNativeSpec: 81ce99032d5b586fddd6a38d450f8595f7e04be4
|
||||
FBLazyVector: ad72713385db5289b19f1ead07e8e4aa26dcb01d
|
||||
FBReactNativeSpec: df2602c11e33d310433496e28a48b4b2be652a61
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 476ee3e89abb49e07f822b48323c51c57124b572
|
||||
RCT-Folly: 4d8508a426467c48885f1151029bc15fa5d7b3b8
|
||||
RCTRequired: 3e917ea5377751094f38145fdece525aa90545a0
|
||||
RCTTypeSafety: c43c072a4bd60feb49a9570b0517892b4305c45e
|
||||
React: 176dd882de001854ced260fad41bb68a31aa4bd0
|
||||
React-callinvoker: c2864d1818d6e64928d2faf774a3800dfc38fe1f
|
||||
React-Codegen: 98b6f97f0a7abf7d67e4ce435c77c05b7a95cf05
|
||||
React-Core: fdaa2916b1c893f39f02cff0476d1fb0cab1e352
|
||||
React-CoreModules: fd8705b80699ec36c2cdd635c2ce9d874b9cfdfc
|
||||
React-cxxreact: 1832d971f7b0cb2c7b943dc0ec962762c90c906e
|
||||
React-jsi: 72af715135abe8c3f0dcf3b2548b71d048b69a7e
|
||||
React-jsiexecutor: b7b553412f2ec768fe6c8f27cd6bafdb9d8719e6
|
||||
React-jsinspector: c5989c77cb89ae6a69561095a61cce56a44ae8e8
|
||||
React-logger: a0833912d93b36b791b7a521672d8ee89107aff1
|
||||
react-native-cameraroll: a40b082318eb1ecd0336a2f29d9f74b7f2c8cae8
|
||||
react-native-pager-view: 592421df0259bf7a7a4fe85b74c24f3f39905605
|
||||
hermes-engine: f6e715aa6c8bd38de6c13bc85e07b0a337edaa89
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||
RCTRequired: fd4d923b964658aa0c4091a32c8b2004c6d9e3a6
|
||||
RCTTypeSafety: c276d85975bde3d8448907235c70bf0da257adfd
|
||||
React: e481a67971af1ce9639c9f746b753dd0e84ca108
|
||||
React-callinvoker: 1051c04a94fa9d243786b86380606bad701a3b31
|
||||
React-Codegen: 14b1e716d361d5ad95e0ce1a338f3fa0733a98b5
|
||||
React-Core: 698fc3baecb80d511d987475a16d036cec6d287f
|
||||
React-CoreModules: 59245305f41ff0adfeac334acc0594dea4585a7c
|
||||
React-cxxreact: 49accd2954b0f532805dbcd1918fa6962f32f247
|
||||
React-hermes: d068733294581a085e95b6024e8d951b005e26d3
|
||||
React-jsi: 122b9bce14f4c6c7cb58f28f87912cfe091885fa
|
||||
React-jsiexecutor: 60cf272aababc5212410e4249d17cea14fc36caa
|
||||
React-jsinspector: ff56004b0c974b688a6548c156d5830ad751ae07
|
||||
React-logger: 60a0b5f8bed667ecf9e24fecca1f30d125de6d75
|
||||
react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
|
||||
react-native-cameraroll: 71d68167beb6fc7216aa564abb6d86f1d666a2c6
|
||||
react-native-image-resizer: 794abf75ec13ed1f0dbb1f134e27504ea65e9e66
|
||||
react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43
|
||||
react-native-paste-input: 5182843692fd2ec72be50f241a38a49796e225d7
|
||||
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-version-number: b415bbec6a13f2df62bf978e85bc0d699462f37f
|
||||
React-perflogger: a18b4f0bd933b8b24ecf9f3c54f9bf65180f3fe6
|
||||
React-RCTActionSheet: 547fe42fdb4b6089598d79f8e1d855d7c23e2162
|
||||
React-RCTAnimation: bc9440a1c37b06ae9ebbb532d244f607805c6034
|
||||
React-RCTBlob: a1295c8e183756d7ef30ba6e8f8144dfe8a19215
|
||||
React-RCTImage: a30d1ee09b1334067fbb6f30789aae2d7ac150c9
|
||||
React-RCTLinking: ffc6d5b88d1cb9aca13c54c2ec6507fbf07f2ac4
|
||||
React-RCTNetwork: f807a2facab6cf5cf36d592e634611de9cf12d81
|
||||
React-RCTSettings: 861806819226ed8332e6a8f90df2951a34bb3e7f
|
||||
React-RCTText: f3fb464cc41a50fc7a1aba4deeb76a9ad8282cb9
|
||||
React-RCTVibration: 79040b92bfa9c3c2d2cb4f57e981164ec7ab9374
|
||||
React-runtimeexecutor: b960b687d2dfef0d3761fbb187e01812ebab8b23
|
||||
ReactCommon: 095366164a276d91ea704ce53cb03825c487a3f2
|
||||
RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca
|
||||
React-perflogger: ec8eef2a8f03ecfa6361c2c5fb9197ef4a29cc85
|
||||
React-RCTActionSheet: a0c023b86cf4c862fa9c4eb0f6f91fbe878fb2de
|
||||
React-RCTAnimation: 168d53718c74153947c0109f55900faa64d79439
|
||||
React-RCTAppDelegate: a8efbab128b34aa07a9491c85a41401210b1bec5
|
||||
React-RCTBlob: 9bcbfc893bfda9f6b2eb016329d38c0f6366d31a
|
||||
React-RCTImage: 3fcd4570b4b0f1ac2f4b4b6308dba33ce66c5b50
|
||||
React-RCTLinking: 1edb8e1bb3fc39bf9e13c63d6aaaa3f0c3d18683
|
||||
React-RCTNetwork: 500a79e0e0f67678077df727fabba87a55c043e1
|
||||
React-RCTSettings: cc4414eb84ad756d619076c3999fecbf12896d6f
|
||||
React-RCTText: 2a34261f3da6e34f47a62154def657546ebfa5e1
|
||||
React-RCTVibration: 49d531ec8498e0afa2c9b22c2205784372e3d4f3
|
||||
React-runtimeexecutor: 311feb67600774723fe10eb8801d3138cae9ad67
|
||||
ReactCommon: 03be76588338a27a88d103b35c3c44a3fd43d136
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNBackgroundFetch: 8e16176ff415daac743a6eb57afc8e9e14dbe623
|
||||
RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60
|
||||
RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd
|
||||
RNGestureHandler: 28ad20bf02257791f7f137b31beef34b9549f54b
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3
|
||||
RNImageCropPicker: 648356d68fbf9911a1016b3e3723885d28373eda
|
||||
RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364
|
||||
RNReanimated: 5bdcbcc3a72aedeee7bb099604262403aa75a1e5
|
||||
RNScreens: 0df01424e9e0ed7827200d6ed1087ddd06c493f9
|
||||
RNSVG: ecd661f380a07ba690c9c5929c475a44f432d674
|
||||
RNNotifee: da8dcf09f079ea22f46e239d7c406e10d4525a5f
|
||||
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
|
||||
RNReanimated: d8d9d3d3801bda5e35e85cdffc871577d044dc2e
|
||||
RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d
|
||||
RNSVG: 6adc5c52d2488a476248413064b7f2832e639057
|
||||
segment-analytics-react-native: cb097e393c3560a0d4cfd877044293e37b0050d9
|
||||
sovran-react-native: fd3dc8f1a4b14acdc4ad25fc6b4ac4f52a2a2a15
|
||||
Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b
|
||||
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
||||
Yoga: 99652481fcd320aefa4a7ef90095b95acd181952
|
||||
Yoga: 921eb014669cf9c718ada68b08d362517d564e0c
|
||||
|
||||
PODFILE CHECKSUM: cf94853ebcb0d8e0d027dca9ab7a4ede886a8f20
|
||||
PODFILE CHECKSUM: 32d3f4ec61d2c786d46fd58000f53917922dbb8a
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
56F0250941FE75DA8CF8094A /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F5D2424078D205E2F98F0707 /* libPods-app-appTests.a */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
BFADB63545C91424F7C8293A /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C668306DD1C0A63684EDCB0 /* libPods-app.a */; };
|
||||
5698CA584FD738B2091BD18F /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0C7BDE7769B84011D3747DC /* libPods-app-appTests.a */; };
|
||||
67BF1AE6AABFC881715B2D6A /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8789F612EDA2C48C6064ADD6 /* libPods-app.a */; };
|
||||
E46FE2C12981C0DB007C107C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E46FE2C02981C0DB007C107C /* LaunchScreen.storyboard */; };
|
||||
E4BBD590292C1F5200296224 /* app.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = E4437C9E28581FA7006DA9E7 /* app.entitlements */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -37,15 +37,15 @@
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = app/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = app/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = app/main.m; sourceTree = "<group>"; };
|
||||
3D3D4D80CD734363E3EADE03 /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
|
||||
65D2EDDD9D88DA37994C7743 /* Pods-app-appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.debug.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = app/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
9C668306DD1C0A63684EDCB0 /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A79BD0E1A3F5B868AD4F5D68 /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
AA0AD1B60CF7C90FFDB948B9 /* Pods-app-appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.release.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
53DBA218C184B95B107AC33E /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
|
||||
8789F612EDA2C48C6064ADD6 /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8BB4EDB104E125B8A1913E74 /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A8E093A0B5DA947150924A68 /* Pods-app-appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.release.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C01FB6762BC17DADC0319338 /* Pods-app-appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.debug.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C0C7BDE7769B84011D3747DC /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E4437C9E28581FA7006DA9E7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = app.entitlements; path = app/app.entitlements; sourceTree = "<group>"; };
|
||||
E46FE2C02981C0DB007C107C /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
F5D2424078D205E2F98F0707 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -53,7 +53,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
56F0250941FE75DA8CF8094A /* libPods-app-appTests.a in Frameworks */,
|
||||
5698CA584FD738B2091BD18F /* libPods-app-appTests.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -61,7 +61,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BFADB63545C91424F7C8293A /* libPods-app.a in Frameworks */,
|
||||
67BF1AE6AABFC881715B2D6A /* libPods-app.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -93,8 +93,8 @@
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
E46FE2C02981C0DB007C107C /* LaunchScreen.storyboard */,
|
||||
);
|
||||
name = app;
|
||||
sourceTree = "<group>";
|
||||
@@ -103,8 +103,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
9C668306DD1C0A63684EDCB0 /* libPods-app.a */,
|
||||
F5D2424078D205E2F98F0707 /* libPods-app-appTests.a */,
|
||||
8789F612EDA2C48C6064ADD6 /* libPods-app.a */,
|
||||
C0C7BDE7769B84011D3747DC /* libPods-app-appTests.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -143,10 +143,10 @@
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A79BD0E1A3F5B868AD4F5D68 /* Pods-app.debug.xcconfig */,
|
||||
3D3D4D80CD734363E3EADE03 /* Pods-app.release.xcconfig */,
|
||||
65D2EDDD9D88DA37994C7743 /* Pods-app-appTests.debug.xcconfig */,
|
||||
AA0AD1B60CF7C90FFDB948B9 /* Pods-app-appTests.release.xcconfig */,
|
||||
8BB4EDB104E125B8A1913E74 /* Pods-app.debug.xcconfig */,
|
||||
53DBA218C184B95B107AC33E /* Pods-app.release.xcconfig */,
|
||||
C01FB6762BC17DADC0319338 /* Pods-app-appTests.debug.xcconfig */,
|
||||
A8E093A0B5DA947150924A68 /* Pods-app-appTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -158,11 +158,12 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "appTests" */;
|
||||
buildPhases = (
|
||||
A8646FFAA087C80271BB2CC6 /* [CP] Check Pods Manifest.lock */,
|
||||
A6849EFFDCB214D4F4EAE972 /* [CP] Check Pods Manifest.lock */,
|
||||
00E356EA1AD99517003FC87E /* Sources */,
|
||||
00E356EB1AD99517003FC87E /* Frameworks */,
|
||||
00E356EC1AD99517003FC87E /* Resources */,
|
||||
8DC349844744C81F79F94A1E /* [CP] Copy Pods Resources */,
|
||||
DFA0C2B14E2F369C4B2337CE /* [CP] Copy Pods Resources */,
|
||||
B73FFC16945F7B215A06B698 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -178,13 +179,14 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "app" */;
|
||||
buildPhases = (
|
||||
AFA1F7779F8B1AF36C3A7914 /* [CP] Check Pods Manifest.lock */,
|
||||
DDF15D430A078CE70E577FDA /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
EEF3465D9B31EDDCEB2438EA /* [CP] Copy Pods Resources */,
|
||||
45E56D79C207C80AF89FBAA2 /* [CP] Copy Pods Resources */,
|
||||
B0229D18A3C8908C642F9131 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -243,8 +245,8 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E46FE2C12981C0DB007C107C /* LaunchScreen.storyboard in Resources */,
|
||||
E4BBD590292C1F5200296224 /* app.entitlements in Resources */,
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -258,32 +260,34 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/.xcode.env.local",
|
||||
"$(SRCROOT)/.xcode.env",
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||
};
|
||||
8DC349844744C81F79F94A1E /* [CP] Copy Pods Resources */ = {
|
||||
45E56D79C207C80AF89FBAA2 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A8646FFAA087C80271BB2CC6 /* [CP] Check Pods Manifest.lock */ = {
|
||||
A6849EFFDCB214D4F4EAE972 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -305,7 +309,41 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
AFA1F7779F8B1AF36C3A7914 /* [CP] Check Pods Manifest.lock */ = {
|
||||
B0229D18A3C8908C642F9131 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
B73FFC16945F7B215A06B698 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DDF15D430A078CE70E577FDA /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -327,21 +365,21 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
EEF3465D9B31EDDCEB2438EA /* [CP] Copy Pods Resources */ = {
|
||||
DFA0C2B14E2F369C4B2337CE /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
@@ -396,7 +434,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00E356F61AD99517003FC87E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 65D2EDDD9D88DA37994C7743 /* Pods-app-appTests.debug.xcconfig */;
|
||||
baseConfigurationReference = C01FB6762BC17DADC0319338 /* Pods-app-appTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
@@ -424,7 +462,7 @@
|
||||
};
|
||||
00E356F71AD99517003FC87E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AA0AD1B60CF7C90FFDB948B9 /* Pods-app-appTests.release.xcconfig */;
|
||||
baseConfigurationReference = A8E093A0B5DA947150924A68 /* Pods-app-appTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
@@ -449,7 +487,7 @@
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A79BD0E1A3F5B868AD4F5D68 /* Pods-app.debug.xcconfig */;
|
||||
baseConfigurationReference = 8BB4EDB104E125B8A1913E74 /* Pods-app.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -459,7 +497,7 @@
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
INFOPLIST_FILE = app/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -479,7 +517,7 @@
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3D3D4D80CD734363E3EADE03 /* Pods-app.release.xcconfig */;
|
||||
baseConfigurationReference = 53DBA218C184B95B107AC33E /* Pods-app.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -488,11 +526,12 @@
|
||||
DEVELOPMENT_TEAM = B3LX46C5HS;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
INFOPLIST_FILE = app/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -538,7 +577,7 @@
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
@@ -554,7 +593,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
@@ -572,6 +611,7 @@
|
||||
"-DFOLLY_MOBILE=1",
|
||||
"-DFOLLY_USE_LIBCPP=1",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -609,7 +649,7 @@
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
@@ -618,7 +658,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
@@ -635,6 +675,7 @@
|
||||
"-DFOLLY_MOBILE=1",
|
||||
"-DFOLLY_USE_LIBCPP=1",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#import <React/RCTBridgeDelegate.h>
|
||||
#import <RCTAppDelegate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
@interface AppDelegate : RCTAppDelegate
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
#import <React/RCTAppSetupUtils.h>
|
||||
|
||||
// universal links
|
||||
#import <React/RCTLinkingManager.h>
|
||||
@@ -12,59 +8,21 @@
|
||||
// splash screen
|
||||
#import "RNSplashScreen.h"
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <React/CoreModulesPlugins.h>
|
||||
#import <React/RCTCxxBridgeDelegate.h>
|
||||
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
||||
#import <React/RCTSurfacePresenter.h>
|
||||
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
||||
|
||||
#import <react/config/ReactNativeConfig.h>
|
||||
|
||||
@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
|
||||
RCTTurboModuleManager *_turboModuleManager;
|
||||
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
|
||||
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
|
||||
facebook::react::ContextContainer::Shared _contextContainer;
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
#import <TSBackgroundFetch/TSBackgroundFetch.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
RCTAppSetupPrepareApp(application);
|
||||
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
|
||||
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
|
||||
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
|
||||
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
|
||||
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
|
||||
#endif
|
||||
|
||||
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"xyz.blueskyweb.app", nil);
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
||||
} else {
|
||||
rootView.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [UIViewController new];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
// Show the splash screen
|
||||
[RNSplashScreen show];
|
||||
// [RNSplashScreen show];
|
||||
|
||||
// Register BackgroundFetch
|
||||
[[TSBackgroundFetch sharedInstance] didFinishLaunching];
|
||||
|
||||
return YES;
|
||||
self.moduleName = @"xyz.blueskyweb.app";
|
||||
self.initialProps = @{};
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||
@@ -76,45 +34,16 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
|
||||
#pragma mark - RCTCxxBridgeDelegate
|
||||
|
||||
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
|
||||
/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
|
||||
///
|
||||
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
|
||||
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
|
||||
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
|
||||
- (BOOL)concurrentRootEnabled
|
||||
{
|
||||
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
|
||||
delegate:self
|
||||
jsInvoker:bridge.jsCallInvoker];
|
||||
return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark RCTTurboModuleManagerDelegate
|
||||
|
||||
- (Class)getModuleClassFromName:(const char *)name
|
||||
{
|
||||
return RCTCoreModulesClassProvider(name);
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
||||
initParams:
|
||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
|
||||
{
|
||||
return RCTAppSetupDefaultModuleFromClass(moduleClass);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// universal links
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
openURL:(NSURL *)url
|
||||
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 347 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 853 B |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 77 KiB |