Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca4d8b85e0 | |||
| 0d26763e11 |
@@ -14,14 +14,14 @@ module.exports = {
|
||||
type: 'ios.app',
|
||||
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/bluesky.app',
|
||||
build:
|
||||
'xcodebuild -workspace ios/Bluesky.xcworkspace -scheme Bluesky -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
|
||||
'xcodebuild -workspace ios/bluesky.xcworkspace -scheme bluesky -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
|
||||
},
|
||||
'ios.release': {
|
||||
type: 'ios.app',
|
||||
binaryPath:
|
||||
'ios/build/Build/Products/Release-iphonesimulator/bluesky.app',
|
||||
build:
|
||||
'xcodebuild -workspace ios/Bluesky.xcworkspace -scheme Bluesky -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
|
||||
'xcodebuild -workspace ios/bluesky.xcworkspace -scheme bluesky -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
|
||||
},
|
||||
'android.debug': {
|
||||
type: 'android.apk',
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
SENTRY_AUTH_TOKEN=
|
||||
@@ -1,10 +1,6 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'@react-native-community',
|
||||
'plugin:react-native-a11y/ios',
|
||||
'prettier',
|
||||
],
|
||||
extends: '@react-native-community',
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'detox'],
|
||||
ignorePatterns: [
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1.
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**Details**
|
||||
|
||||
- Platform: <!-- desktop chrome windows, mobile safari, iOS, Android -->
|
||||
- Platform version:
|
||||
- App version:
|
||||
|
||||
**Additional context**
|
||||
|
||||
<!-- Add any other context about the problem here. -->
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature-request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
**Additional context**
|
||||
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
@@ -18,10 +18,8 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
- name: Yarn install
|
||||
run: yarn
|
||||
- name: Lint check
|
||||
- name: Typescript & Lint check
|
||||
run: yarn lint
|
||||
- name: Type check
|
||||
run: yarn typecheck
|
||||
testing:
|
||||
name: Run tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -82,18 +82,6 @@ web-build/
|
||||
# Temporary files created by Metro to check the health of the file watcher
|
||||
.metro-health-check*
|
||||
|
||||
# VSCode
|
||||
.vscode
|
||||
|
||||
# gitignore and github actions
|
||||
!.gitignore
|
||||
!.github
|
||||
|
||||
|
||||
# Android & iOS folders
|
||||
android/
|
||||
ios/
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.*
|
||||
@@ -17,7 +17,7 @@ ENV CGO_ENABLED=1
|
||||
COPY . .
|
||||
|
||||
#
|
||||
# Generate the JavaScript webpack.
|
||||
# Generate the Javascript webpack.
|
||||
#
|
||||
RUN mkdir --parents $NVM_DIR && \
|
||||
wget \
|
||||
@@ -35,8 +35,11 @@ RUN \. "$NVM_DIR/nvm.sh" && \
|
||||
# DEBUG
|
||||
RUN find ./bskyweb/static && find ./web-build/static
|
||||
|
||||
# Copy the bundle js files.
|
||||
RUN cp --verbose ./web-build/static/js/*.* ./bskyweb/static/js/
|
||||
|
||||
#
|
||||
# Generate the bskyweb Go binary.
|
||||
# Generate the bksyweb Go binary.
|
||||
#
|
||||
RUN cd bskyweb/ && \
|
||||
go mod download && \
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Copyright 2023 Bluesky PBLLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
SHELL = /bin/bash
|
||||
.SHELLFLAGS = -o pipefail -c
|
||||
|
||||
.PHONY: help
|
||||
help: ## Print info about all commands
|
||||
@echo "Commands:"
|
||||
@echo
|
||||
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[01;32m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: build-web
|
||||
build-web: ## Compile web bundle, copy to bskyweb directory
|
||||
yarn build-web
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run all tests
|
||||
yarn test
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## Run style checks and verify syntax
|
||||
yarn run lint
|
||||
|
||||
#.PHONY: fmt
|
||||
#fmt: ## Run syntax re-formatting
|
||||
# yarn prettier
|
||||
|
||||
.PHONY: deps
|
||||
deps: ## Installs dependent libs using 'yarn install'
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
.PHONY: nvm-setup
|
||||
nvm-setup: ## Use NVM to install and activate node+yarn
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
npm install --global yarn
|
||||
@@ -1,61 +1,52 @@
|
||||
# Bluesky Social App
|
||||
# Bluesky
|
||||
|
||||
Welcome friends! This is the codebase for the Bluesky Social app. It serves as a resource to engineers building on the [AT Protocol](https://atproto.com).
|
||||
## Build instructions
|
||||
|
||||
- **Web: [bsky.app](https://bsky.app)**
|
||||
- **iOS: [App Store](https://apps.apple.com/us/app/bluesky-social/id6444370199)**
|
||||
- **Android: [Play Store](https://play.google.com/store/apps/details?id=xyz.blueskyweb.app&hl=en_US&gl=US)**
|
||||
- Setup your environment [using the react native instructions](https://reactnative.dev/docs/environment-setup).
|
||||
- Setup your environment [for e2e testing using detox](https://wix.github.io/Detox/docs/introduction/getting-started):
|
||||
- yarn global add detox-cli
|
||||
- brew tap wix/brew
|
||||
- brew install applesimutils
|
||||
- After initial setup:
|
||||
- `cd ios ; pod install`
|
||||
- Start the dev servers
|
||||
- `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`
|
||||
- Web: `yarn web`
|
||||
- Run e2e tests
|
||||
- Start in various console tabs:
|
||||
- `yarn e2e:server`
|
||||
- `yarn e2e:metro`
|
||||
- Run once: `yarn e2e:build`
|
||||
- Each test run: `yarn e2e:run`
|
||||
- Tips
|
||||
- `npx react-native info` Checks what has been installed.
|
||||
- On M1 macs, [you need to exclude "arm64" from the target architectures](https://stackoverflow.com/a/65399525)
|
||||
- Annoyingly this must be re-set via XCode after every pod install
|
||||
- The android simulator won't be able to access localhost services unless you run `adb reverse tcp:{PORT} tcp:{PORT}`
|
||||
- For instance, the localhosted dev-wallet will need `adb reverse tcp:3001 tcp:3001`
|
||||
- For some reason, the typescript compiler chokes on platform-specific files (e.g. `foo.native.ts`) but only when compiling for Web thus far. Therefore we always have one version of the file which doesn't use a platform specifier, and that should bee the Web version. ([More info](https://stackoverflow.com/questions/44001050/platform-specific-import-component-in-react-native-with-typescript).)
|
||||
|
||||
Links:
|
||||
## Various notes
|
||||
|
||||
- [Build instructions](./docs/build.md)
|
||||
- [ATProto repo](https://github.com/bluesky-social/atproto)
|
||||
- [ATProto docs](https://atproto.com)
|
||||
### Debugging
|
||||
|
||||
## Rules & guidelines
|
||||
- Note that since 0.70, debugging using the old debugger (which shows up using CMD+D) doesn't work anymore. Follow the instructions below to debug the code: https://reactnative.dev/docs/next/hermes#debugging-js-on-hermes-using-google-chromes-devtools
|
||||
|
||||
---
|
||||
### Running E2E Tests
|
||||
|
||||
ℹ️ While we do accept contributions, we prioritize high quality issues and pull requests. Adhering to the below guidelines will ensure a more timely review.
|
||||
- Make sure you've setup your environment following above
|
||||
- Make sure Metro and the dev server are running
|
||||
- Run `yarn e2e`
|
||||
- Find the artifacts in the `artifact` folder
|
||||
|
||||
---
|
||||
### Polyfills
|
||||
|
||||
**Rules:**
|
||||
`./platform/polyfills.*.ts` adds polyfills to the environment. Currently this includes:
|
||||
|
||||
- We may not respond to your issue or PR.
|
||||
- We may close an issue or PR without much feedback.
|
||||
- We may lock discussions or contributions if our attention is getting DDOSed.
|
||||
- We're not going to provide support for build issues.
|
||||
|
||||
**Guidelines:**
|
||||
|
||||
- Check for existing issues before filing a new one please.
|
||||
- Open an issue and give some time for discussion before submitting a PR.
|
||||
- Stay away from PRs like...
|
||||
- Changing "Post" to "Skeet."
|
||||
- Refactoring the codebase, eg to replace mobx with redux or something.
|
||||
- Adding entirely new features without prior discussion.
|
||||
|
||||
Remember, we serve a wide community of users. Our day to day involves us constantly asking "which top priority is our top priority." If you submit well-written PRs that solve problems concisely, that's an awesome contribution. Otherwise, as much as we'd love to accept your ideas and contributions, we really don't have the bandwidth. That's what forking is for!
|
||||
|
||||
## Forking guidelines
|
||||
|
||||
You have our blessing 🪄✨ to fork this application! However, it's very important to be clear to users when you're giving them a fork.
|
||||
|
||||
Please be sure to:
|
||||
|
||||
- Change all branding in the repository and UI to clearly differentiate from Bluesky.
|
||||
- Change any support links (feedback, email, terms of service, etc) to your own systems.
|
||||
- Replace any analytics or error-collection systems with your own so we don't get super confused.
|
||||
|
||||
## Security disclosures
|
||||
|
||||
If you discover any security issues, please send an email to security@bsky.app. The email is automatically CCed to the entire team and we'll respond promptly.
|
||||
|
||||
## License (MIT)
|
||||
|
||||
See [./LICENSE](./LICENSE) for the full license.
|
||||
|
||||
## P.S.
|
||||
|
||||
We ❤️ you and all of the ways you support us. Thank you for making Bluesky a great place!
|
||||
- TextEncoder / TextDecoder
|
||||
|
||||
@@ -13,8 +13,7 @@ async function main() {
|
||||
console.log('Closing old server')
|
||||
await server?.close()
|
||||
console.log('Starting new server')
|
||||
const inviteRequired = url?.query && 'invite' in url.query
|
||||
server = await createServer({inviteRequired})
|
||||
server = await createServer()
|
||||
console.log('Listening at', server.pdsUrl)
|
||||
if (url?.query) {
|
||||
if ('users' in url.query) {
|
||||
@@ -34,9 +33,6 @@ async function main() {
|
||||
displayName: 'Carla',
|
||||
description: 'Test user 3',
|
||||
}))
|
||||
if (inviteRequired) {
|
||||
await server.mocker.createInvite(server.mocker.users.alice.did)
|
||||
}
|
||||
}
|
||||
if ('follows' in url.query) {
|
||||
console.log('Generating mock follows')
|
||||
@@ -66,232 +62,6 @@ async function main() {
|
||||
},
|
||||
})
|
||||
}
|
||||
if ('labels' in url.query) {
|
||||
console.log('Generating naughty users with labels')
|
||||
|
||||
const anchorPost = await server.mocker.createPost(
|
||||
'alice',
|
||||
'Anchor post',
|
||||
)
|
||||
|
||||
for (const user of [
|
||||
'csam-account',
|
||||
'csam-profile',
|
||||
'csam-posts',
|
||||
'porn-account',
|
||||
'porn-profile',
|
||||
'porn-posts',
|
||||
'nudity-account',
|
||||
'nudity-profile',
|
||||
'nudity-posts',
|
||||
'unknown-account',
|
||||
'unknown-profile',
|
||||
'unknown-posts',
|
||||
'always-filter-account',
|
||||
'always-filter-profile',
|
||||
'always-filter-posts',
|
||||
'always-warn-account',
|
||||
'always-warn-profile',
|
||||
'always-warn-posts',
|
||||
'muted-account',
|
||||
'muted-by-list-account',
|
||||
]) {
|
||||
await server.mocker.createUser(user)
|
||||
await server.mocker.follow('alice', user)
|
||||
await server.mocker.follow(user, 'alice')
|
||||
await server.mocker.createPost(user, `Unlabeled post from ${user}`)
|
||||
await server.mocker.createReply(
|
||||
user,
|
||||
`Unlabeled reply from ${user}`,
|
||||
anchorPost,
|
||||
)
|
||||
await server.mocker.like(user, anchorPost)
|
||||
}
|
||||
|
||||
await server.mocker.labelAccount('csam', 'csam-account')
|
||||
await server.mocker.labelProfile('csam', 'csam-profile')
|
||||
await server.mocker.labelPost(
|
||||
'csam',
|
||||
await server.mocker.createPost('csam-posts', 'csam post'),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'csam',
|
||||
await server.mocker.createQuotePost(
|
||||
'csam-posts',
|
||||
'csam quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'csam',
|
||||
await server.mocker.createReply(
|
||||
'csam-posts',
|
||||
'csam reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.labelAccount('porn', 'porn-account')
|
||||
await server.mocker.labelProfile('porn', 'porn-profile')
|
||||
await server.mocker.labelPost(
|
||||
'porn',
|
||||
await server.mocker.createPost('porn-posts', 'porn post'),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'porn',
|
||||
await server.mocker.createQuotePost(
|
||||
'porn-posts',
|
||||
'porn quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'porn',
|
||||
await server.mocker.createReply(
|
||||
'porn-posts',
|
||||
'porn reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.labelAccount('nudity', 'nudity-account')
|
||||
await server.mocker.labelProfile('nudity', 'nudity-profile')
|
||||
await server.mocker.labelPost(
|
||||
'nudity',
|
||||
await server.mocker.createPost('nudity-posts', 'nudity post'),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'nudity',
|
||||
await server.mocker.createQuotePost(
|
||||
'nudity-posts',
|
||||
'nudity quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'nudity',
|
||||
await server.mocker.createReply(
|
||||
'nudity-posts',
|
||||
'nudity reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.labelAccount(
|
||||
'not-a-real-label',
|
||||
'unknown-account',
|
||||
)
|
||||
await server.mocker.labelProfile(
|
||||
'not-a-real-label',
|
||||
'unknown-profile',
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'not-a-real-label',
|
||||
await server.mocker.createPost('unknown-posts', 'unknown post'),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'not-a-real-label',
|
||||
await server.mocker.createQuotePost(
|
||||
'unknown-posts',
|
||||
'unknown quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'not-a-real-label',
|
||||
await server.mocker.createReply(
|
||||
'unknown-posts',
|
||||
'unknown reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.labelAccount('!filter', 'always-filter-account')
|
||||
await server.mocker.labelProfile('!filter', 'always-filter-profile')
|
||||
await server.mocker.labelPost(
|
||||
'!filter',
|
||||
await server.mocker.createPost(
|
||||
'always-filter-posts',
|
||||
'always-filter post',
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'!filter',
|
||||
await server.mocker.createQuotePost(
|
||||
'always-filter-posts',
|
||||
'always-filter quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'!filter',
|
||||
await server.mocker.createReply(
|
||||
'always-filter-posts',
|
||||
'always-filter reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.labelAccount('!warn', 'always-warn-account')
|
||||
await server.mocker.labelProfile('!warn', 'always-warn-profile')
|
||||
await server.mocker.labelPost(
|
||||
'!warn',
|
||||
await server.mocker.createPost(
|
||||
'always-warn-posts',
|
||||
'always-warn post',
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'!warn',
|
||||
await server.mocker.createQuotePost(
|
||||
'always-warn-posts',
|
||||
'always-warn quote post',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
await server.mocker.labelPost(
|
||||
'!warn',
|
||||
await server.mocker.createReply(
|
||||
'always-warn-posts',
|
||||
'always-warn reply',
|
||||
anchorPost,
|
||||
),
|
||||
)
|
||||
|
||||
await server.mocker.users.alice.agent.mute('muted-account.test')
|
||||
await server.mocker.createPost('muted-account', 'muted post')
|
||||
await server.mocker.createQuotePost(
|
||||
'muted-account',
|
||||
'muted quote post',
|
||||
anchorPost,
|
||||
)
|
||||
await server.mocker.createReply(
|
||||
'muted-account',
|
||||
'muted reply',
|
||||
anchorPost,
|
||||
)
|
||||
|
||||
const list = await server.mocker.createMuteList(
|
||||
'alice',
|
||||
'Muted Users',
|
||||
)
|
||||
await server.mocker.addToMuteList(
|
||||
'alice',
|
||||
list,
|
||||
server.mocker.users['muted-by-list-account'].did,
|
||||
)
|
||||
await server.mocker.createPost('muted-by-list-account', 'muted post')
|
||||
await server.mocker.createQuotePost(
|
||||
'muted-by-list-account',
|
||||
'account quote post',
|
||||
anchorPost,
|
||||
)
|
||||
await server.mocker.createReply(
|
||||
'muted-by-list-account',
|
||||
'account reply',
|
||||
anchorPost,
|
||||
)
|
||||
}
|
||||
}
|
||||
console.log('Ready')
|
||||
return res.writeHead(200).end(server.pdsUrl)
|
||||
|
||||
@@ -5,7 +5,7 @@ import {openApp, createServer} from '../util'
|
||||
describe('Create account', () => {
|
||||
let service: string
|
||||
beforeAll(async () => {
|
||||
service = await createServer('')
|
||||
service = await createServer('mock0')
|
||||
await openApp({permissions: {notifications: 'YES'}})
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@ describe('Create account', () => {
|
||||
await element(by.id('nextBtn')).tap()
|
||||
await element(by.id('emailInput')).typeText('example@test.com')
|
||||
await element(by.id('passwordInput')).typeText('hunter2')
|
||||
await element(by.id('is13Input')).tap()
|
||||
await device.takeScreenshot('4- entered account details')
|
||||
await element(by.id('nextBtn')).tap()
|
||||
await element(by.id('handleInput')).typeText('e2e-test')
|
||||
|
||||
@@ -57,9 +57,7 @@ describe('Home screen', () => {
|
||||
.tap()
|
||||
await element(by.id('postDropdownReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).toBeVisible()
|
||||
await element(
|
||||
by.id('reportPostRadios-com.atproto.moderation.defs#reasonSpam'),
|
||||
).tap()
|
||||
await element(by.id('reportPostRadios-spam')).tap()
|
||||
await element(by.id('sendReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).not.toBeVisible()
|
||||
})
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/* eslint-env detox/detox */
|
||||
|
||||
import {openApp, login, createServer} from '../util'
|
||||
|
||||
describe('invite-codes', () => {
|
||||
let service: string
|
||||
let inviteCode = ''
|
||||
beforeAll(async () => {
|
||||
service = await createServer('?users&invite')
|
||||
await openApp({permissions: {notifications: 'YES'}})
|
||||
})
|
||||
|
||||
it('I can fetch invite codes', async () => {
|
||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
||||
await login(service, 'alice', 'hunter2')
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await expect(element(by.id('drawer'))).toBeVisible()
|
||||
await element(by.id('menuItemInviteCodes')).tap()
|
||||
await expect(element(by.id('inviteCodesModal'))).toBeVisible()
|
||||
const attrs = await element(by.id('inviteCode-0-code')).getAttributes()
|
||||
inviteCode = attrs.text
|
||||
await element(by.id('closeBtn')).tap()
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('I can create a new account with the invite code', async () => {
|
||||
await element(by.id('createAccountButton')).tap()
|
||||
await device.takeScreenshot('1- opened create account screen')
|
||||
await element(by.id('otherServerBtn')).tap()
|
||||
await device.takeScreenshot('2- selected other server')
|
||||
await element(by.id('customServerInput')).clearText()
|
||||
await element(by.id('customServerInput')).typeText(service)
|
||||
await device.takeScreenshot('3- input test server URL')
|
||||
await element(by.id('nextBtn')).tap()
|
||||
await element(by.id('inviteCodeInput')).typeText(inviteCode)
|
||||
await element(by.id('emailInput')).typeText('example@test.com')
|
||||
await element(by.id('passwordInput')).typeText('hunter2')
|
||||
await device.takeScreenshot('4- entered account details')
|
||||
await element(by.id('nextBtn')).tap()
|
||||
await element(by.id('handleInput')).typeText('e2e-test')
|
||||
await device.takeScreenshot('4- entered handle')
|
||||
await element(by.id('nextBtn')).tap()
|
||||
await expect(element(by.id('homeScreen'))).toBeVisible()
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('I get a notification for the new user', async () => {
|
||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
||||
await login(service, 'alice', 'hunter2')
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Notifications')).tap()
|
||||
await expect(element(by.id('invitedUser'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('I can dismiss the new user notification', async () => {
|
||||
await element(by.id('dismissBtn')).tap()
|
||||
await expect(element(by.id('invitedUser'))).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -1,141 +0,0 @@
|
||||
/* eslint-env detox/detox */
|
||||
|
||||
import {openApp, login, createServer, sleep} from '../util'
|
||||
|
||||
describe('Profile screen', () => {
|
||||
let service: string
|
||||
beforeAll(async () => {
|
||||
service = await createServer('?users&follows&labels')
|
||||
await openApp({
|
||||
permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'},
|
||||
})
|
||||
})
|
||||
|
||||
it('Login and view my mutelists', async () => {
|
||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
||||
await login(service, 'alice', 'hunter2')
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await expect(element(by.id('drawer'))).toBeVisible()
|
||||
await element(by.id('menuItemButton-Moderation')).tap()
|
||||
await element(by.id('mutelistsBtn')).tap()
|
||||
await expect(element(by.id('list-Muted Users'))).toBeVisible()
|
||||
await element(by.id('list-Muted Users')).tap()
|
||||
await expect(
|
||||
element(by.id('user-muted-by-list-account.test')),
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
it('Toggle subscription', async () => {
|
||||
await element(by.id('unsubscribeListBtn')).tap()
|
||||
await element(by.id('subscribeListBtn')).tap()
|
||||
})
|
||||
|
||||
it('Edit display name and description via the edit mutelist modal', async () => {
|
||||
await element(by.id('editListBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).toBeVisible()
|
||||
await element(by.id('editNameInput')).clearText()
|
||||
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
||||
await element(by.id('editDescriptionInput')).clearText()
|
||||
await element(by.id('editDescriptionInput')).typeText('They bad')
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).not.toBeVisible()
|
||||
await expect(element(by.id('listName'))).toHaveText('Bad Ppl')
|
||||
await expect(element(by.id('listDescription'))).toHaveText('They bad')
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('editListBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
})
|
||||
|
||||
it('Remove description via the edit mutelist modal', async () => {
|
||||
await element(by.id('editListBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).toBeVisible()
|
||||
await element(by.id('editDescriptionInput')).clearText()
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).not.toBeVisible()
|
||||
await expect(element(by.id('listDescription'))).not.toBeVisible()
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('editListBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
})
|
||||
|
||||
it('Set avi via the edit mutelist modal', async () => {
|
||||
await expect(element(by.id('userAvatarFallback'))).toExist()
|
||||
await element(by.id('editListBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).toBeVisible()
|
||||
await element(by.id('changeAvatarBtn')).tap()
|
||||
await element(by.id('changeAvatarLibraryBtn')).tap()
|
||||
await sleep(3e3)
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).not.toBeVisible()
|
||||
await expect(element(by.id('userAvatarImage'))).toExist()
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('editListBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
})
|
||||
|
||||
it('Remove avi via the edit mutelist modal', async () => {
|
||||
await expect(element(by.id('userAvatarImage'))).toExist()
|
||||
await element(by.id('editListBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).toBeVisible()
|
||||
await element(by.id('changeAvatarBtn')).tap()
|
||||
await element(by.id('changeAvatarRemoveBtn')).tap()
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).not.toBeVisible()
|
||||
await expect(element(by.id('userAvatarFallback'))).toExist()
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('editListBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
})
|
||||
|
||||
it('Delete the mutelist', async () => {
|
||||
await element(by.id('deleteListBtn')).tap()
|
||||
await element(by.id('confirmBtn')).tap()
|
||||
await expect(element(by.id('emptyMuteLists'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('Create a new mutelist', async () => {
|
||||
await element(by.id('emptyMuteLists-button')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).toBeVisible()
|
||||
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
||||
await element(by.id('editDescriptionInput')).typeText('They bad')
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('createOrEditMuteListModal'))).not.toBeVisible()
|
||||
await expect(element(by.id('listName'))).toHaveText('Bad Ppl')
|
||||
await expect(element(by.id('listDescription'))).toHaveText('They bad')
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('editListBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
})
|
||||
|
||||
it('Shows the mutelist on my profile', async () => {
|
||||
await element(by.id('bottomBarProfileBtn')).tap()
|
||||
await element(by.id('selector-2')).tap()
|
||||
await element(by.id('list-Bad Ppl')).tap()
|
||||
})
|
||||
|
||||
it('Adds and removes users on mutelists', async () => {
|
||||
await element(by.id('bottomBarSearchBtn')).tap()
|
||||
await element(by.id('searchTextInput')).typeText('bob')
|
||||
await element(by.id('searchAutoCompleteResult-bob.test')).tap()
|
||||
await expect(element(by.id('profileView'))).toBeVisible()
|
||||
|
||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||
await element(by.id('profileHeaderDropdownListAddRemoveBtn')).tap()
|
||||
await expect(element(by.id('listAddRemoveUserModal'))).toBeVisible()
|
||||
await element(by.id('toggleBtn-Bad Ppl')).tap()
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('listAddRemoveUserModal'))).not.toBeVisible()
|
||||
|
||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||
await element(by.id('profileHeaderDropdownListAddRemoveBtn')).tap()
|
||||
await expect(element(by.id('listAddRemoveUserModal'))).toBeVisible()
|
||||
await element(by.id('toggleBtn-Bad Ppl')).tap()
|
||||
await element(by.id('saveBtn')).tap()
|
||||
await expect(element(by.id('listAddRemoveUserModal'))).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -93,7 +93,7 @@ describe('Profile screen', () => {
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('searchTextInput')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
.withTimeout(2000)
|
||||
await element(by.id('searchTextInput')).typeText('bob')
|
||||
await element(by.id('searchAutoCompleteResult-bob.test')).tap()
|
||||
await expect(element(by.id('profileView'))).toBeVisible()
|
||||
@@ -120,9 +120,7 @@ describe('Profile screen', () => {
|
||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||
await element(by.id('profileHeaderDropdownReportBtn')).tap()
|
||||
await expect(element(by.id('reportAccountModal'))).toBeVisible()
|
||||
await element(
|
||||
by.id('reportAccountRadios-com.atproto.moderation.defs#reasonSpam'),
|
||||
).tap()
|
||||
await element(by.id('reportAccountRadios-spam')).tap()
|
||||
await element(by.id('sendReportBtn')).tap()
|
||||
await expect(element(by.id('reportAccountModal'))).not.toBeVisible()
|
||||
})
|
||||
@@ -168,9 +166,7 @@ describe('Profile screen', () => {
|
||||
await element(by.id('postDropdownBtn').withAncestor(posts)).atIndex(0).tap()
|
||||
await element(by.id('postDropdownReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).toBeVisible()
|
||||
await element(
|
||||
by.id('reportPostRadios-com.atproto.moderation.defs#reasonSpam'),
|
||||
).tap()
|
||||
await element(by.id('reportPostRadios-spam')).tap()
|
||||
await element(by.id('sendReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).not.toBeVisible()
|
||||
})
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/* eslint-env detox/detox */
|
||||
|
||||
import {openApp, login, createServer} from '../util'
|
||||
|
||||
describe('Thread muting', () => {
|
||||
let service: string
|
||||
beforeAll(async () => {
|
||||
service = await createServer('?users&follows')
|
||||
await openApp({permissions: {notifications: 'YES'}})
|
||||
})
|
||||
|
||||
it('Login, create a thread, and log out', async () => {
|
||||
await login(service, 'alice', 'hunter2')
|
||||
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
||||
await element(by.id('composeFAB')).tap()
|
||||
await element(by.id('composerTextInput')).typeText('Test thread')
|
||||
await element(by.id('composerPublishBtn')).tap()
|
||||
await expect(element(by.id('composeFAB'))).toBeVisible()
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('Login, reply to the thread, and log out', async () => {
|
||||
await login(service, 'bob', 'hunter2')
|
||||
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
||||
const alicePosts = by.id('feedItem-by-alice.test')
|
||||
await element(by.id('replyBtn').withAncestor(alicePosts)).atIndex(0).tap()
|
||||
await element(by.id('composerTextInput')).typeText('Reply 1')
|
||||
await element(by.id('composerPublishBtn')).tap()
|
||||
await expect(element(by.id('composeFAB'))).toBeVisible()
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('Login, confirm notification exists, mute thread, and log out', async () => {
|
||||
await login(service, 'alice', 'hunter2')
|
||||
|
||||
await element(by.id('bottomBarNotificationsBtn')).tap()
|
||||
const bobNotifs = by.id('feedItem-by-bob.test')
|
||||
await expect(
|
||||
element(by.id('postText').withAncestor(bobNotifs)).atIndex(0),
|
||||
).toHaveText('Reply 1')
|
||||
await element(by.id('postDropdownBtn').withAncestor(bobNotifs))
|
||||
.atIndex(0)
|
||||
.tap()
|
||||
await element(by.id('postDropdownMuteThreadBtn')).tap()
|
||||
// have to wait for the toast to clear
|
||||
await waitFor(element(by.id('viewHeaderDrawerBtn')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000)
|
||||
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('Login, reply to the thread twice, and log out', async () => {
|
||||
await login(service, 'bob', 'hunter2')
|
||||
|
||||
await element(by.id('bottomBarProfileBtn')).tap()
|
||||
await element(by.id('selector-1')).tap()
|
||||
const bobPosts = by.id('feedItem-by-bob.test')
|
||||
await element(by.id('replyBtn').withAncestor(bobPosts)).atIndex(0).tap()
|
||||
await element(by.id('composerTextInput')).typeText('Reply 2')
|
||||
await element(by.id('composerPublishBtn')).tap()
|
||||
await expect(element(by.id('composeFAB'))).toBeVisible()
|
||||
|
||||
const alicePosts = by.id('feedItem-by-alice.test')
|
||||
await element(by.id('replyBtn').withAncestor(alicePosts)).atIndex(0).tap()
|
||||
await element(by.id('composerTextInput')).typeText('Reply 3')
|
||||
await element(by.id('composerPublishBtn')).tap()
|
||||
await expect(element(by.id('composeFAB'))).toBeVisible()
|
||||
|
||||
await element(by.id('bottomBarHomeBtn')).tap()
|
||||
await element(by.id('viewHeaderDrawerBtn')).tap()
|
||||
await element(by.id('menuItemButton-Settings')).tap()
|
||||
await element(by.id('signOutBtn')).tap()
|
||||
})
|
||||
|
||||
it('Login, confirm notifications dont exist, unmute the thread, confirm notifications exist', async () => {
|
||||
await login(service, 'alice', 'hunter2')
|
||||
|
||||
await element(by.id('bottomBarNotificationsBtn')).tap()
|
||||
const bobNotifs = by.id('feedItem-by-bob.test')
|
||||
await expect(
|
||||
element(by.id('postText').withAncestor(bobNotifs)).atIndex(0),
|
||||
).not.toExist()
|
||||
|
||||
await element(by.id('bottomBarHomeBtn')).tap()
|
||||
const alicePosts = by.id('feedItem-by-alice.test')
|
||||
await element(by.id('postDropdownBtn').withAncestor(alicePosts))
|
||||
.atIndex(0)
|
||||
.tap()
|
||||
await element(by.id('postDropdownMuteThreadBtn')).tap()
|
||||
|
||||
// TODO
|
||||
// the swipe down to trigger PTR isnt working and I dont want to block on this
|
||||
// -prf
|
||||
// await element(by.id('bottomBarNotificationsBtn')).tap()
|
||||
// await element(by.id('notifsFeed')).swipe('down', 'fast')
|
||||
// await waitFor(element(by.id('postText').withAncestor(bobNotifs)))
|
||||
// .toBeVisible()
|
||||
// .withTimeout(5000)
|
||||
// await expect(
|
||||
// element(by.id('postText').withAncestor(bobNotifs)).atIndex(0),
|
||||
// ).toHaveText('Reply 2')
|
||||
// await expect(
|
||||
// element(by.id('postText').withAncestor(bobNotifs)).atIndex(1),
|
||||
// ).toHaveText('Reply 3')
|
||||
// await expect(
|
||||
// element(by.id('postText').withAncestor(bobNotifs)).atIndex(2),
|
||||
// ).toHaveText('Reply 1')
|
||||
})
|
||||
})
|
||||
@@ -106,9 +106,7 @@ describe('Thread screen', () => {
|
||||
await element(by.id('postDropdownBtn').withAncestor(post)).atIndex(0).tap()
|
||||
await element(by.id('postDropdownReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).toBeVisible()
|
||||
await element(
|
||||
by.id('reportPostRadios-com.atproto.moderation.defs#reasonSpam'),
|
||||
).tap()
|
||||
await element(by.id('reportPostRadios-spam')).tap()
|
||||
await element(by.id('sendReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).not.toBeVisible()
|
||||
})
|
||||
@@ -118,9 +116,7 @@ describe('Thread screen', () => {
|
||||
await element(by.id('postDropdownBtn').withAncestor(post)).atIndex(0).tap()
|
||||
await element(by.id('postDropdownReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).toBeVisible()
|
||||
await element(
|
||||
by.id('reportPostRadios-com.atproto.moderation.defs#reasonSpam'),
|
||||
).tap()
|
||||
await element(by.id('reportPostRadios-spam')).tap()
|
||||
await element(by.id('sendReportBtn')).tap()
|
||||
await expect(element(by.id('reportPostModal'))).not.toBeVisible()
|
||||
})
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
import {resolveConfig} from 'detox/internals'
|
||||
import {execSync} from 'child_process'
|
||||
|
||||
const platform = device.getPlatform()
|
||||
|
||||
export async function openApp(opts: any) {
|
||||
opts = opts || {}
|
||||
const config = await resolveConfig()
|
||||
|
||||
if (device.getPlatform() === 'ios') {
|
||||
// disable password autofill
|
||||
execSync(
|
||||
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist`,
|
||||
)
|
||||
execSync(
|
||||
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist`,
|
||||
)
|
||||
execSync(
|
||||
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist`,
|
||||
)
|
||||
}
|
||||
if (config.configurationName.split('.').includes('debug')) {
|
||||
return await openAppForDebugBuild(platform, opts)
|
||||
} else {
|
||||
@@ -56,7 +42,6 @@ export async function login(
|
||||
await device.takeScreenshot('2- opened service selector')
|
||||
}
|
||||
await element(by.id('customServerTextInput')).typeText(service)
|
||||
await element(by.id('customServerTextInput')).tapReturnKey()
|
||||
await element(by.id('customServerSelectBtn')).tap()
|
||||
if (takeScreenshots) {
|
||||
await device.takeScreenshot('3- input custom service')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {ReactNode} from 'react'
|
||||
import React from 'react'
|
||||
import {View, ScrollView, Modal, FlatList, TextInput} from 'react-native'
|
||||
|
||||
const BottomSheetModalContext = React.createContext(null)
|
||||
@@ -6,10 +6,7 @@ const BottomSheetModalContext = React.createContext(null)
|
||||
const BottomSheetModalProvider = (props: any) => {
|
||||
return <BottomSheetModalContext.Provider {...props} value={{}} />
|
||||
}
|
||||
class BottomSheet extends React.Component<{
|
||||
onClose?: () => void
|
||||
children?: ReactNode
|
||||
}> {
|
||||
class BottomSheet extends React.Component<{onClose?: () => void}> {
|
||||
snapToIndex() {}
|
||||
snapToPosition() {}
|
||||
expand() {}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const getLocales = jest.fn().mockResolvedValue([])
|
||||
@@ -1,4 +1,106 @@
|
||||
import {LikelyType, getLikelyType} from '../../src/lib/link-meta/link-meta'
|
||||
import {
|
||||
LikelyType,
|
||||
getLinkMeta,
|
||||
getLikelyType,
|
||||
} from '../../src/lib/link-meta/link-meta'
|
||||
import {exampleComHtml} from './__mocks__/exampleComHtml'
|
||||
import {BskyAgent} from '@atproto/api'
|
||||
import {DEFAULT_SERVICE, RootStoreModel} from '../../src/state'
|
||||
|
||||
describe('getLinkMeta', () => {
|
||||
let rootStore: RootStoreModel
|
||||
|
||||
beforeEach(() => {
|
||||
rootStore = new RootStoreModel(new BskyAgent({service: DEFAULT_SERVICE}))
|
||||
})
|
||||
|
||||
const inputs = [
|
||||
'',
|
||||
'httpbadurl',
|
||||
'https://example.com',
|
||||
'https://example.com/index.html',
|
||||
'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 = [
|
||||
{
|
||||
error: 'Invalid URL',
|
||||
likelyType: LikelyType.Other,
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
error: 'Invalid URL',
|
||||
likelyType: LikelyType.Other,
|
||||
url: 'httpbadurl',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.HTML,
|
||||
url: 'https://example.com',
|
||||
title: 'Example Domain',
|
||||
description: 'An example website',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.HTML,
|
||||
url: 'https://example.com/index.html',
|
||||
title: 'Example Domain',
|
||||
description: 'An example website',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.Image,
|
||||
url: 'https://example.com/image.png',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.Video,
|
||||
url: 'https://example.com/video.avi',
|
||||
},
|
||||
{
|
||||
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: '/',
|
||||
},
|
||||
{
|
||||
likelyType: LikelyType.AtpData,
|
||||
url: '/index.html',
|
||||
},
|
||||
{
|
||||
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) => {
|
||||
resolve({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: () => exampleComHtml,
|
||||
})
|
||||
})
|
||||
})
|
||||
const input = inputs[i]
|
||||
const output = await getLinkMeta(rootStore, input)
|
||||
expect(output).toEqual(outputs[i])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('getLikelyType', () => {
|
||||
it('correctly handles non-parsed url', async () => {
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('detectLinkables', () => {
|
||||
'Classic article https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/ ',
|
||||
'https://foo.com https://bar.com/whatever https://baz.com',
|
||||
'punctuation https://foo.com, https://bar.com/whatever; https://baz.com.',
|
||||
'parenthetical (https://foo.com)',
|
||||
'parenthentical (https://foo.com)',
|
||||
'except for https://foo.com/thing_(cool)',
|
||||
]
|
||||
const outputs = [
|
||||
@@ -112,7 +112,7 @@ describe('detectLinkables', () => {
|
||||
{link: 'https://baz.com'},
|
||||
'.',
|
||||
],
|
||||
['parenthetical (', {link: 'https://foo.com'}, ')'],
|
||||
['parenthentical (', {link: 'https://foo.com'}, ')'],
|
||||
['except for ', {link: 'https://foo.com/thing_(cool)'}],
|
||||
]
|
||||
it('correctly handles a set of text inputs', () => {
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
|
||||
def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()
|
||||
def expoDebuggableVariants = ['debug']
|
||||
// Override `debuggableVariants` for expo-updates debugging
|
||||
if (System.getenv('EX_UPDATES_NATIVE_DEBUG') == "1") {
|
||||
react {
|
||||
expoDebuggableVariants = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
react {
|
||||
entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
|
||||
reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
|
||||
hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
|
||||
debuggableVariants = expoDebuggableVariants
|
||||
|
||||
/* 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"]
|
||||
}
|
||||
|
||||
// Override `hermesEnabled` by `expo.jsEngine`
|
||||
ext {
|
||||
hermesEnabled = (findProperty('expo.jsEngine') ?: "hermes") == "hermes"
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
/**
|
||||
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean()
|
||||
|
||||
/**
|
||||
* 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
|
||||
* this variant is about 6MiB larger per architecture than default.
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
|
||||
/**
|
||||
* 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")
|
||||
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
||||
}
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
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.0"
|
||||
}
|
||||
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
include (*reactNativeArchitectures())
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
storePassword 'android'
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://reactnative.dev/docs/signed-apk-android.
|
||||
signingConfig signingConfigs.debug
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
}
|
||||
}
|
||||
|
||||
// applicationVariants are e.g. debug, release
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
// For each separate APK per architecture, set a unique version code as described here:
|
||||
// https://developer.android.com/studio/build/configure-apk-splits.html
|
||||
// Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
|
||||
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
defaultConfig.versionCode * 1000 + versionCodes.get(abi)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply static values from `gradle.properties` to the `android.packagingOptions`
|
||||
// Accepts values in comma delimited lists, example:
|
||||
// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini
|
||||
["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop ->
|
||||
// Split option: 'foo,bar' -> ['foo', 'bar']
|
||||
def options = (findProperty("android.packagingOptions.$prop") ?: "").split(",");
|
||||
// Trim all elements in place.
|
||||
for (i in 0..<options.size()) options[i] = options[i].trim();
|
||||
// `[] - ""` is essentially `[""].filter(Boolean)` removing all empty strings.
|
||||
options -= ""
|
||||
|
||||
if (options.length > 0) {
|
||||
println "android.packagingOptions.$prop += $options ($options.length)"
|
||||
// Ex: android.packagingOptions.pickFirsts += '**/SCCS/**'
|
||||
options.each {
|
||||
android.packagingOptions[prop] += it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
|
||||
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
|
||||
def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";
|
||||
def frescoVersion = rootProject.ext.frescoVersion
|
||||
|
||||
// If your app supports Android versions before Ice Cream Sandwich (API level 14)
|
||||
if (isGifEnabled || isWebpEnabled) {
|
||||
implementation("com.facebook.fresco:fresco:${frescoVersion}")
|
||||
implementation("com.facebook.fresco:imagepipeline-okhttp3:${frescoVersion}")
|
||||
}
|
||||
|
||||
if (isGifEnabled) {
|
||||
// For animated gif support
|
||||
implementation("com.facebook.fresco:animated-gif:${frescoVersion}")
|
||||
}
|
||||
|
||||
if (isWebpEnabled) {
|
||||
// For webp support
|
||||
implementation("com.facebook.fresco:webpsupport:${frescoVersion}")
|
||||
if (isWebpAnimatedEnabled) {
|
||||
// Animated webp support
|
||||
implementation("com.facebook.fresco:animated-webp:${frescoVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
|
||||
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.squareup.okhttp3', module:'okhttp'
|
||||
}
|
||||
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
|
||||
|
||||
if (hermesEnabled.toBoolean()) {
|
||||
implementation("com.facebook.react:hermes-android")
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesAppBuildGradle(project)
|
||||
@@ -0,0 +1,14 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# react-native-reanimated
|
||||
-keep class com.swmansion.reanimated.** { *; }
|
||||
-keep class com.facebook.react.turbomodule.** { *; }
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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.flipper.android.AndroidFlipperClient;
|
||||
import com.facebook.flipper.android.utils.FlipperUtils;
|
||||
import com.facebook.flipper.core.FlipperClient;
|
||||
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
|
||||
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
|
||||
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
|
||||
import com.facebook.react.ReactInstanceEventListener;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
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 DatabasesFlipperPlugin(context));
|
||||
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||
|
||||
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
|
||||
NetworkingModule.setCustomClientBuilder(
|
||||
new NetworkingModule.CustomClientBuilder() {
|
||||
@Override
|
||||
public void apply(OkHttpClient.Builder builder) {
|
||||
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
|
||||
}
|
||||
});
|
||||
client.addPlugin(networkFlipperPlugin);
|
||||
client.start();
|
||||
|
||||
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
|
||||
// Hence we run if after all native modules have been initialized
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext == null) {
|
||||
reactInstanceManager.addReactInstanceEventListener(
|
||||
new ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(ReactContext reactContext) {
|
||||
reactInstanceManager.removeReactInstanceEventListener(this);
|
||||
reactContext.runOnNativeModulesQueueThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
client.addPlugin(new FrescoFlipperPlugin());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
client.addPlugin(new FrescoFlipperPlugin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="xyz.blueskyweb.app">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="https"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true">
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="48.0.0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@arrygoo/bluesky"/> <!-- TODO -->
|
||||
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="xyz.blueskyweb.app"/>
|
||||
<data android:scheme="exp+bluesky"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,68 @@
|
||||
package xyz.blueskyweb.app;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate;
|
||||
|
||||
import expo.modules.ReactActivityDelegateWrapper;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// This is required for expo-splash-screen.
|
||||
setTheme(R.style.AppTheme);
|
||||
super.onCreate(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript.
|
||||
* This is used to schedule rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "main";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, new DefaultReactActivityDelegate(
|
||||
this,
|
||||
getMainComponentName(),
|
||||
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
|
||||
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
|
||||
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
|
||||
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Align the back button behavior with Android S
|
||||
* where moving root activities to background instead of finishing activities.
|
||||
* @see <a href="https://developer.android.com/reference/android/app/Activity#onBackPressed()">onBackPressed</a>
|
||||
*/
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
if (!moveTaskToBack(false)) {
|
||||
// For non-root activities, use the default implementation to finish them.
|
||||
super.invokeDefaultOnBackPressed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the default back button implementation on Android S
|
||||
// because it's doing more than {@link Activity#moveTaskToBack} in fact.
|
||||
super.invokeDefaultOnBackPressed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package xyz.blueskyweb.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.res.Configuration;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
import expo.modules.ApplicationLifecycleDispatcher;
|
||||
import expo.modules.ReactNativeHostWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNewArchEnabled() {
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean isHermesEnabled() {
|
||||
return BuildConfig.IS_HERMES_ENABLED;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
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());
|
||||
ApplicationLifecycleDispatcher.onApplicationCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetTop="@dimen/abc_edit_text_inset_top_material"
|
||||
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
|
||||
|
||||
<selector>
|
||||
<!--
|
||||
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
|
||||
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
|
||||
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
|
||||
|
||||
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
|
||||
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
|
||||
-->
|
||||
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
|
||||
</selector>
|
||||
|
||||
</inset>
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">bsky</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,9 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '33.0.0'
|
||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '21')
|
||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '33')
|
||||
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '33')
|
||||
if (findProperty('android.kotlinVersion')) {
|
||||
kotlinVersion = findProperty('android.kotlinVersion')
|
||||
}
|
||||
frescoVersion = findProperty('expo.frescoVersion') ?: '2.5.0'
|
||||
|
||||
// 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.3.1')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url(new File(['node', '--print', "require.resolve('jsc-android/package.json')"].execute(null, rootDir).text.trim(), '../dist'))
|
||||
}
|
||||
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
# Version of flipper SDK to use with React Native
|
||||
FLIPPER_VERSION=0.125.0
|
||||
|
||||
# Use this property to specify which architecture you want to build.
|
||||
# You can also override it from the CLI using
|
||||
# ./gradlew <task> -PreactNativeArchitectures=x86_64
|
||||
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
|
||||
# Use this property to enable support to the new architecture.
|
||||
# This will allow you to use TurboModules and the Fabric render in
|
||||
# your application. You should enable this flag either if you want
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
|
||||
# The hosted JavaScript engine
|
||||
# Supported values: expo.jsEngine = "hermes" | "jsc"
|
||||
expo.jsEngine=hermes
|
||||
|
||||
# Enable GIF support in React Native images (~200 B increase)
|
||||
expo.gif.enabled=true
|
||||
# Enable webp support in React Native images (~85 KB increase)
|
||||
expo.webp.enabled=true
|
||||
# Enable animated webp support (~3.4 MB increase)
|
||||
# Disabled by default because iOS doesn't support animated webp
|
||||
expo.webp.animated=false
|
||||
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,240 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -0,0 +1,91 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,10 @@
|
||||
rootProject.name = 'bluesky'
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
||||
useExpoModules()
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesSettingsGradle(settings)
|
||||
|
||||
include ':app'
|
||||
includeBuild(new File(["node", "--print", "require.resolve('react-native-gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile())
|
||||
@@ -1,111 +1,32 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Bluesky",
|
||||
"name": "bluesky",
|
||||
"slug": "bluesky",
|
||||
"scheme": "bluesky",
|
||||
"owner": "blueskysocial",
|
||||
"version": "1.41.0",
|
||||
"runtimeVersion": {
|
||||
"policy": "appVersion"
|
||||
},
|
||||
"version": "1.12.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/cloud-splash.png",
|
||||
"resizeMode": "cover",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"buildNumber": "2",
|
||||
"supportsTablet": false,
|
||||
"bundleIdentifier": "xyz.blueskyweb.app",
|
||||
"config": {
|
||||
"usesNonExemptEncryption": false
|
||||
},
|
||||
"infoPlist": {
|
||||
"UIBackgroundModes": [
|
||||
"fetch",
|
||||
"processing"
|
||||
],
|
||||
"BGTaskSchedulerPermittedIdentifiers": [
|
||||
"com.transistorsoft.fetch"
|
||||
],
|
||||
"NSCameraUsageDescription": "Used for profile pictures, posts, and other kinds of content.",
|
||||
"NSMicrophoneUsageDescription": "Used for posts and other kinds of content.",
|
||||
"NSPhotoLibraryAddUsageDescription": "Used to save images to your library.",
|
||||
"NSPhotoLibraryUsageDescription": "Used for profile pictures, posts, and other kinds of content"
|
||||
},
|
||||
"associatedDomains": ["applinks:bsky.app", "applinks:staging.bsky.app"]
|
||||
},
|
||||
"androidStatusBar": {
|
||||
"barStyle": "dark-content",
|
||||
"backgroundColor": "#ffffff"
|
||||
"bundleIdentifier": "xyz.blueskyweb.app"
|
||||
},
|
||||
"android": {
|
||||
"versionCode": 27,
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "xyz.blueskyweb.app",
|
||||
"intentFilters": [
|
||||
{
|
||||
"action": "VIEW",
|
||||
"autoVerify": true,
|
||||
"data": [
|
||||
{
|
||||
"scheme": "https",
|
||||
"host": "bsky.app"
|
||||
}
|
||||
],
|
||||
"category": ["BROWSABLE", "DEFAULT"]
|
||||
}
|
||||
]
|
||||
"package": "xyz.blueskyweb.app"
|
||||
},
|
||||
"web": {
|
||||
"favicon": "./assets/favicon.png"
|
||||
},
|
||||
"updates": {
|
||||
"enabled": true,
|
||||
"fallbackToCacheTimeout": 1000,
|
||||
"url": "https://u.expo.dev/55bd077a-d905-4184-9c7f-94789ba0f302"
|
||||
},
|
||||
"plugins": [
|
||||
"expo-localization",
|
||||
"react-native-background-fetch",
|
||||
"sentry-expo",
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"android": {
|
||||
"compileSdkVersion": 34,
|
||||
"kotlinVersion": "1.8.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"expo-updates",
|
||||
{
|
||||
"username": "blueskysocial"
|
||||
}
|
||||
]
|
||||
],
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "55bd077a-d905-4184-9c7f-94789ba0f302"
|
||||
}
|
||||
},
|
||||
"hooks": {
|
||||
"postPublish": [
|
||||
{
|
||||
"file": "sentry-expo/upload-sourcemaps",
|
||||
"config": {
|
||||
"organization": "blueskyweb",
|
||||
"project": "react-native"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"expo-localization"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,5 @@ test-coverage.out
|
||||
# Don't check in the binary.
|
||||
/bskyweb
|
||||
|
||||
# Don't accidentally commit JS-generated code
|
||||
static/js/*.js
|
||||
static/js/*.map
|
||||
static/js/*.js.LICENSE.txt
|
||||
templates/scripts.html
|
||||
|
||||
# Don't ignore this file
|
||||
!.gitignore
|
||||
|
||||
@@ -39,4 +39,4 @@ check: ## Compile everything, checking syntax (does not output binaries)
|
||||
|
||||
.PHONY: run-dev-bskyweb
|
||||
run-dev-bskyweb: .env ## Runs 'bskyweb' for local dev
|
||||
GOLOG_LOG_LEVEL=info go run ./cmd/bskyweb serve --debug
|
||||
GOLOG_LOG_LEVEL=info go run ./cmd/bskyweb serve
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### SPA Bundle (monolithic static javascript file)
|
||||
|
||||
To build the SPA bundle (`bundle.web.js`), first get a JavaScript development
|
||||
To build the SPA bundle (`bundle.web.js`), first get a Javascript development
|
||||
environment set up. Either follow the top-level README, or something quick
|
||||
like:
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/bskyweb
|
||||
@@ -14,15 +14,13 @@ type Mailmodo struct {
|
||||
httpClient *http.Client
|
||||
APIKey string
|
||||
BaseURL string
|
||||
ListName string
|
||||
}
|
||||
|
||||
func NewMailmodo(apiKey, listName string) *Mailmodo {
|
||||
func NewMailmodo(apiKey string) *Mailmodo {
|
||||
return &Mailmodo{
|
||||
APIKey: apiKey,
|
||||
BaseURL: "https://api.mailmodo.com/api/v1",
|
||||
httpClient: &http.Client{},
|
||||
ListName: listName,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +56,9 @@ func (m *Mailmodo) request(ctx context.Context, httpMethod string, apiMethod str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mailmodo) AddToList(ctx context.Context, email string) error {
|
||||
func (m *Mailmodo) AddToList(ctx context.Context, listName, email string) error {
|
||||
return m.request(ctx, "POST", "addToList", map[string]any{
|
||||
"listName": m.ListName,
|
||||
"listName": listName,
|
||||
"email": email,
|
||||
"data": map[string]any{
|
||||
"email_hashed": fmt.Sprintf("%x", sha256.Sum256([]byte(email))),
|
||||
|
||||
@@ -2,17 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
comatproto "github.com/bluesky-social/indigo/api/atproto"
|
||||
appbsky "github.com/bluesky-social/indigo/api/bsky"
|
||||
@@ -21,18 +15,13 @@ import (
|
||||
"github.com/bluesky-social/social-app/bskyweb"
|
||||
|
||||
"github.com/flosch/pongo2/v6"
|
||||
"github.com/klauspost/compress/gzhttp"
|
||||
"github.com/klauspost/compress/gzip"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
echo *echo.Echo
|
||||
httpd *http.Server
|
||||
mailmodo *Mailmodo
|
||||
xrpcc *xrpc.Client
|
||||
xrpcc *xrpc.Client
|
||||
}
|
||||
|
||||
func serve(cctx *cli.Context) error {
|
||||
@@ -44,11 +33,8 @@ func serve(cctx *cli.Context) error {
|
||||
mailmodoAPIKey := cctx.String("mailmodo-api-key")
|
||||
mailmodoListName := cctx.String("mailmodo-list-name")
|
||||
|
||||
// Echo
|
||||
e := echo.New()
|
||||
|
||||
// Mailmodo client.
|
||||
mailmodo := NewMailmodo(mailmodoAPIKey, mailmodoListName)
|
||||
mailmodo := NewMailmodo(mailmodoAPIKey)
|
||||
|
||||
// create a new session
|
||||
// TODO: does this work with no auth at all?
|
||||
@@ -61,7 +47,7 @@ func serve(cctx *cli.Context) error {
|
||||
}
|
||||
|
||||
auth, err := comatproto.ServerCreateSession(context.TODO(), xrpcc, &comatproto.ServerCreateSession_Input{
|
||||
Identifier: xrpcc.Auth.Handle,
|
||||
Identifier: &xrpcc.Auth.Handle,
|
||||
Password: atpPassword,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -72,76 +58,10 @@ func serve(cctx *cli.Context) error {
|
||||
xrpcc.Auth.Did = auth.Did
|
||||
xrpcc.Auth.Handle = auth.Handle
|
||||
|
||||
// httpd
|
||||
var (
|
||||
httpTimeout = 2 * time.Minute
|
||||
httpMaxHeaderBytes = 2 * (1024 * 1024)
|
||||
gzipMinSizeBytes = 1024 * 2
|
||||
gzipCompressionLevel = gzip.BestSpeed
|
||||
gzipExceptMIMETypes = []string{"image/png"}
|
||||
)
|
||||
server := Server{xrpcc}
|
||||
|
||||
// Wrap the server handler in a gzip handler to compress larger responses.
|
||||
gzipHandler, err := gzhttp.NewWrapper(
|
||||
gzhttp.MinSize(gzipMinSizeBytes),
|
||||
gzhttp.CompressionLevel(gzipCompressionLevel),
|
||||
gzhttp.ExceptContentTypes(gzipExceptMIMETypes),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//
|
||||
// server
|
||||
//
|
||||
server := &Server{
|
||||
echo: e,
|
||||
mailmodo: mailmodo,
|
||||
xrpcc: xrpcc,
|
||||
}
|
||||
|
||||
// Create the HTTP server.
|
||||
server.httpd = &http.Server{
|
||||
Handler: gzipHandler(server),
|
||||
Addr: httpAddress,
|
||||
WriteTimeout: httpTimeout,
|
||||
ReadTimeout: httpTimeout,
|
||||
MaxHeaderBytes: httpMaxHeaderBytes,
|
||||
}
|
||||
|
||||
e.HideBanner = true
|
||||
// SECURITY: Do not modify without due consideration.
|
||||
e.Use(middleware.SecureWithConfig(middleware.SecureConfig{
|
||||
ContentTypeNosniff: "nosniff",
|
||||
XFrameOptions: "SAMEORIGIN",
|
||||
HSTSMaxAge: 31536000, // 365 days
|
||||
// TODO:
|
||||
// ContentSecurityPolicy
|
||||
// XSSProtection
|
||||
}))
|
||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||
// Don't log requests for static content.
|
||||
Skipper: func(c echo.Context) bool {
|
||||
return strings.HasPrefix(c.Request().URL.Path, "/static")
|
||||
},
|
||||
}))
|
||||
e.Renderer = NewRenderer("templates/", &bskyweb.TemplateFS, debug)
|
||||
e.HTTPErrorHandler = server.errorHandler
|
||||
|
||||
// redirect trailing slash to non-trailing slash.
|
||||
// all of our current endpoints have no trailing slash.
|
||||
e.Use(middleware.RemoveTrailingSlashWithConfig(middleware.TrailingSlashConfig{
|
||||
RedirectCode: http.StatusFound,
|
||||
}))
|
||||
|
||||
//
|
||||
// configure routes
|
||||
//
|
||||
|
||||
// static files
|
||||
staticHandler := http.FileServer(func() http.FileSystem {
|
||||
if debug {
|
||||
log.Debugf("serving static file from the local file system")
|
||||
return http.FS(os.DirFS("static"))
|
||||
}
|
||||
fsys, err := fs.Sub(bskyweb.StaticFS, "static")
|
||||
@@ -150,98 +70,58 @@ func serve(cctx *cli.Context) error {
|
||||
}
|
||||
return http.FS(fsys)
|
||||
}())
|
||||
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||
// Don't log requests for static content.
|
||||
Skipper: func(c echo.Context) bool {
|
||||
return strings.HasPrefix(c.Request().URL.Path, "/static")
|
||||
},
|
||||
Format: "method=${method} path=${uri} status=${status} latency=${latency_human}\n",
|
||||
}))
|
||||
e.Renderer = NewRenderer("templates/", &bskyweb.TemplateFS, debug)
|
||||
e.HTTPErrorHandler = customHTTPErrorHandler
|
||||
|
||||
// configure routes
|
||||
e.GET("/robots.txt", echo.WrapHandler(staticHandler))
|
||||
e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", staticHandler)))
|
||||
e.GET("/.well-known/*", echo.WrapHandler(staticHandler))
|
||||
e.GET("/security.txt", func(c echo.Context) error {
|
||||
return c.Redirect(http.StatusMovedPermanently, "/.well-known/security.txt")
|
||||
})
|
||||
|
||||
// home
|
||||
e.GET("/", server.WebHome)
|
||||
|
||||
// generic routes
|
||||
e.GET("/search", server.WebGeneric)
|
||||
e.GET("/search/feeds", server.WebGeneric)
|
||||
e.GET("/feeds", server.WebGeneric)
|
||||
e.GET("/notifications", server.WebGeneric)
|
||||
e.GET("/moderation", server.WebGeneric)
|
||||
e.GET("/moderation/mute-lists", server.WebGeneric)
|
||||
e.GET("/moderation/muted-accounts", server.WebGeneric)
|
||||
e.GET("/moderation/blocked-accounts", server.WebGeneric)
|
||||
e.GET("/settings", server.WebGeneric)
|
||||
e.GET("/settings/app-passwords", server.WebGeneric)
|
||||
e.GET("/settings/saved-feeds", server.WebGeneric)
|
||||
e.GET("/sys/debug", server.WebGeneric)
|
||||
e.GET("/sys/log", server.WebGeneric)
|
||||
e.GET("/support", server.WebGeneric)
|
||||
e.GET("/support/privacy", server.WebGeneric)
|
||||
e.GET("/support/tos", server.WebGeneric)
|
||||
e.GET("/support/community-guidelines", server.WebGeneric)
|
||||
e.GET("/support/copyright", server.WebGeneric)
|
||||
|
||||
// profile endpoints; only first populates info
|
||||
e.GET("/profile/:handle", server.WebProfile)
|
||||
e.GET("/profile/:handle/follows", server.WebGeneric)
|
||||
e.GET("/profile/:handle/followers", server.WebGeneric)
|
||||
e.GET("/profile/:handle/lists/:rkey", server.WebGeneric)
|
||||
e.GET("/profile/:handle/feed/:rkey", server.WebGeneric)
|
||||
e.GET("/profile/:handle/feed/:rkey/liked-by", server.WebGeneric)
|
||||
|
||||
// post endpoints; only first populates info
|
||||
e.GET("/profile/:handle/post/:rkey", server.WebPost)
|
||||
e.GET("/profile/:handle/post/:rkey/liked-by", server.WebGeneric)
|
||||
e.GET("/profile/:handle/post/:rkey/upvoted-by", server.WebGeneric)
|
||||
e.GET("/profile/:handle/post/:rkey/downvoted-by", server.WebGeneric)
|
||||
e.GET("/profile/:handle/post/:rkey/reposted-by", server.WebGeneric)
|
||||
|
||||
// Mailmodo
|
||||
e.POST("/api/waitlist", server.apiWaitlist)
|
||||
e.POST("/waitlist", func(c echo.Context) error {
|
||||
email := strings.TrimSpace(c.FormValue("email"))
|
||||
if err := mailmodo.AddToList(c.Request().Context(), mailmodoListName, email); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(http.StatusOK, map[string]bool{"success": true})
|
||||
})
|
||||
|
||||
// Start the server.
|
||||
log.Infof("starting server address=%s", httpAddress)
|
||||
go func() {
|
||||
if err := server.httpd.ListenAndServe(); err != nil {
|
||||
if !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Errorf("HTTP server shutting down unexpectedly: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for a signal to exit.
|
||||
log.Info("registering OS exit signal handler")
|
||||
quit := make(chan struct{})
|
||||
exitSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(exitSignals, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
sig := <-exitSignals
|
||||
log.Infof("received OS exit signal: %s", sig)
|
||||
|
||||
// Shut down the HTTP server.
|
||||
if err := server.Shutdown(); err != nil {
|
||||
log.Errorf("HTTP server shutdown error: %s", err)
|
||||
}
|
||||
|
||||
// Trigger the return that causes an exit.
|
||||
close(quit)
|
||||
}()
|
||||
<-quit
|
||||
log.Infof("graceful shutdown complete")
|
||||
return nil
|
||||
return e.Start(httpAddress)
|
||||
}
|
||||
|
||||
func (srv *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
srv.echo.ServeHTTP(rw, req)
|
||||
}
|
||||
|
||||
func (srv *Server) Shutdown() error {
|
||||
log.Info("shutting down")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
return srv.httpd.Shutdown(ctx)
|
||||
}
|
||||
|
||||
func (srv *Server) errorHandler(err error, c echo.Context) {
|
||||
func customHTTPErrorHandler(err error, c echo.Context) {
|
||||
code := http.StatusInternalServerError
|
||||
if he, ok := err.(*echo.HTTPError); ok {
|
||||
code = he.Code
|
||||
@@ -285,13 +165,7 @@ func (srv *Server) WebPost(c echo.Context) error {
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch post: %s\t%v", uri, err)
|
||||
} else {
|
||||
req := c.Request()
|
||||
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
|
||||
data["postView"] = postView
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
if postView.Embed != nil && postView.Embed.EmbedImages_View != nil {
|
||||
data["imgThumbUrl"] = postView.Embed.EmbedImages_View.Images[0].Thumb
|
||||
}
|
||||
data["postView"] = tpv.Thread.FeedDefs_ThreadViewPost.Post
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,44 +183,9 @@ func (srv *Server) WebProfile(c echo.Context) error {
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch handle: %s\t%v", handle, err)
|
||||
} else {
|
||||
req := c.Request()
|
||||
data["profileView"] = pv
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
}
|
||||
}
|
||||
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
|
||||
func (srv *Server) apiWaitlist(c echo.Context) error {
|
||||
type jsonError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Read the API request.
|
||||
type apiRequest struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
bodyReader := http.MaxBytesReader(c.Response(), c.Request().Body, 16*1024)
|
||||
payload, err := ioutil.ReadAll(bodyReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var req apiRequest
|
||||
if err := json.Unmarshal(payload, &req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, jsonError{Error: "Invalid API request"})
|
||||
}
|
||||
|
||||
if req.Email == "" {
|
||||
return c.JSON(http.StatusBadRequest, jsonError{Error: "Please enter a valid email address."})
|
||||
}
|
||||
|
||||
if err := srv.mailmodo.AddToList(c.Request().Context(), req.Email); err != nil {
|
||||
log.Errorf("adding email to waitlist failed: %s", err)
|
||||
return c.JSON(http.StatusBadRequest, jsonError{
|
||||
Error: "Storing email in waitlist failed. Please enter a valid email address.",
|
||||
})
|
||||
}
|
||||
return c.JSON(http.StatusOK, map[string]bool{"success": true})
|
||||
}
|
||||
|
||||
@@ -3,19 +3,18 @@ module github.com/bluesky-social/social-app/bskyweb
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319
|
||||
github.com/bluesky-social/indigo v0.0.0-20230402165318-56d29448c031
|
||||
github.com/flosch/pongo2/v6 v6.0.0
|
||||
github.com/ipfs/go-log v1.0.5
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/klauspost/compress v1.16.5
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/urfave/cli/v2 v2.25.3
|
||||
github.com/urfave/cli/v2 v2.25.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
@@ -27,7 +26,7 @@ require (
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/ipfs/bbloom v0.0.4 // indirect
|
||||
github.com/ipfs/go-block-format v0.1.2 // indirect
|
||||
github.com/ipfs/go-cid v0.4.1 // indirect
|
||||
github.com/ipfs/go-cid v0.4.0 // indirect
|
||||
github.com/ipfs/go-datastore v0.6.0 // indirect
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
|
||||
@@ -69,22 +68,22 @@ require (
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70 // indirect
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.opentelemetry.io/otel v1.15.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.15.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
gorm.io/driver/postgres v1.5.0 // indirect
|
||||
gorm.io/driver/sqlite v1.5.0 // indirect
|
||||
gorm.io/gorm v1.25.0 // indirect
|
||||
gorm.io/driver/sqlite v1.4.4 // indirect
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
||||
|
||||
@@ -2,8 +2,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319 h1:VCNXRXpgyK3xkaQ8fzL5WzswerwLycke4B9ggLs1uOA=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319/go.mod h1:Hc09SUJXAIujaAvq7JXxi8ZQQI887grzPkHgn4JyE1Q=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230402165318-56d29448c031 h1:njihDcG7w2dZLxv3B2uxi1jtxLg+GYglyEpMcjsiqmU=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230402165318-56d29448c031/go.mod h1:9dcnKLtEnDPBdWm5/BLJHvbaPndCdKzAaBK7sbGt3S4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
@@ -12,9 +12,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@@ -56,8 +55,8 @@ github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUP
|
||||
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
|
||||
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
|
||||
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
|
||||
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||
github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA=
|
||||
github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
|
||||
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
|
||||
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
|
||||
@@ -97,6 +96,7 @@ github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0
|
||||
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
@@ -105,8 +105,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
@@ -211,8 +209,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
|
||||
github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
|
||||
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
@@ -220,8 +218,8 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 h1:XYEgH2nJgsrcrj32p+SAbx6T3s/6QknOXezXtz7kzbg=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70 h1:iNBzUKTsJc9RqStEVX2VYgVHATTU39IuB7g0e8OPWXU=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230331140348-1f892b517e70/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 h1:EO/9z3yDvx1van1/0esdcqhalZZQGRj3I1BPTWr5k3A=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220/go.mod h1:qPtRyexGM5XMHFIfjH+EiA/A/1n2JakWEdMPC53pJAE=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
@@ -230,14 +228,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8=
|
||||
go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc=
|
||||
go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY=
|
||||
go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
@@ -257,9 +255,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -276,9 +273,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -301,9 +297,8 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -312,9 +307,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -349,11 +343,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
|
||||
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
|
||||
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
|
||||
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
|
||||
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"applinks": {
|
||||
"apps": [],
|
||||
"details": [
|
||||
{
|
||||
"appID": "B3LX46C5HS.xyz.blueskyweb.app",
|
||||
"paths": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
[
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "xyz.blueskyweb.app",
|
||||
"sha256_cert_fingerprints":
|
||||
["C1:4D:3C:6B:B5:D6:D9:AE:CF:C5:0B:BC:C1:9B:29:6D:D4:E6:87:46:36:D5:4C:1A:64:1C:14:08:BF:7E:F9:62", "FA:C6:17:45:DC:09:03:78:6F:B9:ED:E6:2A:96:2B:39:9F:73:48:F0:BB:6F:89:9B:83:32:66:75:91:03:3B:9C"]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,4 +0,0 @@
|
||||
Contact: mailto:security@bsky.app
|
||||
Preferred-Languages: en
|
||||
Canonical: https://bsky.app/.well-known/security.txt
|
||||
Acknowledgements: https://github.com/bluesky-social/atproto/blob/main/CONTRIBUTORS.md
|
||||
@@ -1,9 +1 @@
|
||||
# Hello Friends!
|
||||
# If you are considering bulk or automated crawling, you may want to look in
|
||||
# to our protocol (API), including a firehose of updates. See: https://atproto.com/
|
||||
|
||||
# By default, may crawl anything on this domain. HTTP 429 ("backoff") status
|
||||
# codes are used for rate-limiting. Up to a handful concurrent requests should
|
||||
# be ok.
|
||||
User-Agent: *
|
||||
Allow: /
|
||||
# hello friends!
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover">
|
||||
<meta charset="UTF-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover">
|
||||
<meta name="referrer" content="origin-when-cross-origin">
|
||||
<title>{%- block head_title -%}Bluesky{%- endblock -%}</title>
|
||||
|
||||
@@ -56,6 +57,10 @@
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Remove focus state on inputs */
|
||||
*:focus {
|
||||
outline: 0;
|
||||
}
|
||||
/* Remove default link styling */
|
||||
a {
|
||||
color: inherit;
|
||||
@@ -63,23 +68,12 @@
|
||||
a[role="link"]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
a[role="link"][data-no-underline="1"]:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Styling hacks */
|
||||
*[data-word-wrap] {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* ProseMirror */
|
||||
.ProseMirror {
|
||||
font: 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
min-height: 140px;
|
||||
}
|
||||
.ProseMirror-dark {
|
||||
color: white;
|
||||
}
|
||||
.ProseMirror p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -97,35 +91,58 @@
|
||||
color: #0085ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* OLLIE: TODO -- this is not accessible */
|
||||
/* Remove focus state on inputs */
|
||||
.ProseMirror-focused {
|
||||
outline: 0;
|
||||
}
|
||||
textarea:focus,
|
||||
input:focus {
|
||||
outline: 0;
|
||||
}
|
||||
.tippy-content .items {
|
||||
width: fit-content;
|
||||
border-radius: 6px;
|
||||
background: #F3F3F8;
|
||||
border: 1px solid #e0d9d9;
|
||||
padding: 3px 3px;
|
||||
}
|
||||
.tippy-content .items .item {
|
||||
display: block;
|
||||
background: transparent;
|
||||
color: #8a8c9a;
|
||||
border: 0;
|
||||
font: 17px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
padding: 7px 10px 8px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
.tippy-content .items .item.is-selected {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
{% include "scripts.html" %}
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
|
||||
{% block html_head_extra -%}{%- endblock %}
|
||||
<meta name="application-name" name="Bluesky">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"/>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"/>
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"/>
|
||||
{% block head_page_meta -%}
|
||||
<meta property="og:title" content="Bluesky Social"/>
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta property="og:image" content="/static/default-social-card.png"/>
|
||||
<meta name="twitter:title" content="Bluesky Social"/>
|
||||
<meta name="twitter:description" content="See what's next."/>
|
||||
<meta name="twitter:image" content="/static/default-social-card.png"/>
|
||||
<meta name="twitter:card" content="summary_large_image"/>
|
||||
<meta name="twitter:site" content="@bluesky"/>
|
||||
{%- endblock %}
|
||||
<!-- TODO: link rel=canonical -->
|
||||
<!-- TODO: analytics code -->
|
||||
<!-- TODO: could put <link rel="preload"> tags here -->
|
||||
<meta name="generator" name="bskyweb">
|
||||
{% block head_metadata %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{%- block body_all %}
|
||||
<div id="root"></div>
|
||||
<noscript>
|
||||
<h1>JavaScript Required</h1>
|
||||
<p>This is a heavily interactive web application, and JavaScript is required. Simple HTML interfaces are possible, but that is not what this is.
|
||||
{%- block noscript_extra %}{% endblock -%}
|
||||
<h1>Javascript Required</h1>
|
||||
<p>This is a heavily interactive web application, and Javascript is required. Simple HTML interfaces are possible, but that is not what this is.
|
||||
<p>Learn more about Bluesky at <a href="https://blueskyweb.xyz">blueskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>.
|
||||
{% block noscript_extra %}{% endblock %}
|
||||
</noscript>
|
||||
{% endblock -%}
|
||||
</body>
|
||||
|
||||
@@ -2,16 +2,6 @@
|
||||
|
||||
{% block head_title %}Bluesky{% endblock %}
|
||||
|
||||
{% block html_head_extra -%}
|
||||
<meta name="description" content="See what's next.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Bluesky Social">
|
||||
<meta property="og:description" content="See what's next.">
|
||||
<meta property="og:image" content="/static/social-card-default.png">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
{%- endblock %}
|
||||
|
||||
{% block noscript_extra %}
|
||||
<p>This is the home page.
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,48 +1,25 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block head_title %}
|
||||
{% block head_page_meta -%}
|
||||
<!-- TODO: "same as" indication with at:// URI? -->
|
||||
{%- if postView -%}
|
||||
@{{ postView.Author.Handle }} on Bluesky
|
||||
{%- else -%}
|
||||
Bluesky
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
{%- if postView.Author.DisplayName -%}
|
||||
<meta property="og:title" content="{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }}"/>
|
||||
<meta name="twitter:title" content="{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }}"/>
|
||||
{%- else -%}
|
||||
<meta property="og:title" content="{{ postView.Author.Handle }}"/>
|
||||
<meta name="twitter:title" content="{{ postView.Author.Handle }}"/>
|
||||
{%- endif -%}
|
||||
{%- if postView.Record.Text -%}
|
||||
<meta name="twitter:description" content="{{ postView.Record.Text }}"/>
|
||||
<!-- TODO: could put any images in here, or author avatar -->
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% endblock %}
|
||||
|
||||
{% block html_head_extra -%}
|
||||
{%- if postView -%}
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Bluesky Social">
|
||||
{%- if requestURI %}
|
||||
<meta property="og:url" content="{{ requestURI }}">
|
||||
{% endif -%}
|
||||
{%- if postView.Author.DisplayName %}
|
||||
<meta property="og:title" content="{{ postView.Author.DisplayName }} (@{{ postView.Author.Handle }})">
|
||||
{% else %}
|
||||
<meta property="og:title" content="@{{ postView.Author.Handle }}">
|
||||
{% endif -%}
|
||||
{%- if postView.Record.Val.Text %}
|
||||
<meta name="description" content="{{ postView.Record.Val.Text }}">
|
||||
<meta property="og:description" content="{{ postView.Record.Val.Text }}">
|
||||
{% endif -%}
|
||||
{%- if imgThumbUrl %}
|
||||
<meta property="og:image" content="{{ imgThumbUrl }}">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
{%- elif postView.Author.Avatar %}
|
||||
{# Don't use avatar image in cards; usually looks bad #}
|
||||
<meta name="twitter:card" content="summary">
|
||||
{% endif %}
|
||||
<meta name="twitter:label1" content="Posted At">
|
||||
<meta name="twitter:value1" content="{{ postView.CreatedAt }}">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
{% block noscript_extra -%}
|
||||
<div id="bsky_post_summary">
|
||||
<h3>Post</h3>
|
||||
<p id="bsky_display_name">{{ postView.Author.DisplayName }}</p>
|
||||
<p id="bsky_handle">{{ postView.Author.Handle }}</p>
|
||||
<p id="bsky_did">{{ postView.Author.Did }}</p>
|
||||
<p id="bsky_post_text">{{ postView.Record.Val.Text }}</p>
|
||||
</div>
|
||||
<p>{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }}
|
||||
<p>{{ postView.Record.Text }}
|
||||
{%- endblock %}
|
||||
|
||||
@@ -1,48 +1,25 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block head_title %}
|
||||
{% block head_page_meta -%}
|
||||
<!-- TODO: "same as" indication with DID? -->
|
||||
{%- if profileView -%}
|
||||
@{{ profileView.Handle }} on Bluesky
|
||||
{%- else -%}
|
||||
Bluesky
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
{%- if profileView.DisplayName -%}
|
||||
<meta property="og:title" content="{{ profileView.DisplayName }} / {{ profileView.Handle }}"/>
|
||||
<meta name="twitter:title" content="{{ profileView.DisplayName }} / {{ profileView.Handle }}"/>
|
||||
{%- else -%}
|
||||
<meta property="og:title" content="{{ profileView.Handle }}"/>
|
||||
<meta name="twitter:title" content="{{ profileView.Handle }}"/>
|
||||
{%- endif -%}
|
||||
<meta name="twitter:description" content="{{ profileView.Description }}"/>
|
||||
{%- if profileView.Avatar -%}
|
||||
<meta name="twitter:image" content="{{ profileView.Avatar }}"/>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% endblock %}
|
||||
|
||||
{% block html_head_extra -%}
|
||||
{%- if profileView -%}
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Bluesky Social">
|
||||
{%- if requestURI %}
|
||||
<meta property="og:url" content="{{ requestURI }}">
|
||||
{% endif -%}
|
||||
{%- if profileView.DisplayName %}
|
||||
<meta property="og:title" content="{{ profileView.DisplayName }} (@{{ profileView.Handle }})">
|
||||
{% else %}
|
||||
<meta property="og:title" content="{{ profileView.Handle }}">
|
||||
{% endif -%}
|
||||
{%- if profileView.Description %}
|
||||
<meta name="description" content="{{ profileView.Description }}">
|
||||
<meta property="og:description" content="{{ profileView.Description }}">
|
||||
{% endif -%}
|
||||
{%- if profileView.Banner %}
|
||||
<meta property="og:image" content="{{ profileView.Banner }}">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
{%- elif profileView.Avatar -%}
|
||||
{# Don't use avatar image in cards; usually looks bad #}
|
||||
<meta name="twitter:card" content="summary">
|
||||
{% endif %}
|
||||
<meta name="twitter:label1" content="Account DID">
|
||||
<meta name="twitter:value1" content="{{ profileView.Did }}">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
{% block noscript_extra -%}
|
||||
<div id="bsky_profile_summary">
|
||||
<h3>Profile</h3>
|
||||
<p id="bsky_display_name">{{ profileView.DisplayName }}</p>
|
||||
<p id="bsky_handle">{{ profileView.Handle }}</p>
|
||||
<p id="bsky_did">{{ profileView.Did }}</p>
|
||||
<p id="bsky_profile_description">{{ profileView.Description }}</p>
|
||||
</div>
|
||||
<p>{{ profileView.DisplayName }} / {{ profileView.Handle }}
|
||||
<p>{{ profileView.Description }}
|
||||
{%- endblock %}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
# Build instructions
|
||||
|
||||
## App Build
|
||||
|
||||
- Setup your environment [using the react native instructions](https://reactnative.dev/docs/environment-setup).
|
||||
- Setup your environment [for e2e testing using detox](https://wix.github.io/Detox/docs/introduction/getting-started):
|
||||
- yarn global add detox-cli
|
||||
- brew tap wix/brew
|
||||
- brew install applesimutils
|
||||
- After initial setup:
|
||||
- `npx expo prebuild` -> you will also need to run this anytime `app.json` or `package.json` changes
|
||||
- Start the dev servers
|
||||
- `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`
|
||||
- Web: `yarn web`
|
||||
- If you are cloning or forking this repo as an open source developer, please check the tips below as well
|
||||
- Run e2e tests
|
||||
- Start in various console tabs:
|
||||
- `yarn e2e:mock-server`
|
||||
- `yarn e2e:metro`
|
||||
- Run once: `yarn e2e:build`
|
||||
- Each test run: `yarn e2e:run`
|
||||
- Tips
|
||||
- Make sure you copy the `.env.example` to `.env` and add the appropriate tokens (e.g. `SENTRY_AUTH_TOKEN` can be created on the Sentry dashboard using [these instructions](https://docs.expo.dev/guides/using-sentry/#sign-up-for-a-sentry-account-and-create-a-project)). If this is not required, you can remove it from `eas.json` and `package.json`, as well as any mentions in the code. Please check the section below on how to remove Sentry from the codebase
|
||||
- If you want to use Expo EAS on your own builds without ejecting from Expo, make sure to change the `owner` as well as `extra.eas.projectId` properties. If you do not have an Expo account, you may remove these properties.
|
||||
- `npx react-native info` Checks what has been installed.
|
||||
- The android simulator won't be able to access localhost services unless you run `adb reverse tcp:{PORT} tcp:{PORT}`
|
||||
- For instance, the locally-hosted dev-wallet will need `adb reverse tcp:3001 tcp:3001`
|
||||
- For some reason, the typescript compiler chokes on platform-specific files (e.g. `foo.native.ts`) but only when compiling for Web thus far. Therefore we always have one version of the file which doesn't use a platform specifier, and that should be the Web version. ([More info](https://stackoverflow.com/questions/44001050/platform-specific-import-component-in-react-native-with-typescript).)
|
||||
|
||||
### Removing Sentry
|
||||
If you are part of the Bluesky team, you should have access to our Sentry dashboard, and you shouldn't need to remove Sentry. Even if you are not part of the Bluesky team, you can create your own Sentry account and add the `SENTRY_AUTH_TOKEN` env var and add your sentry account detials to `app.json` to make the app build and run successfully. However, if that is not possible, follow these steps to remove Sentry from the project (please don't commit this code in any PR):
|
||||
- `yarn remove sentry-expo @sentry/react-native`
|
||||
- Remove `sentry-expo` plugin in `app.json` and also remove the `postPublish` hook in `app.json`
|
||||
- Remove any mentions of `sentry` from the `App.native.tsx`, `App.web.tsx` and `Navigation.tsx` files. Also, delete `sentry.ts`
|
||||
- Run `rm -rf ios android` or delete the existing `android` and `ios` folders in the project (don't worry! `yarn prebuild` gets these back)
|
||||
- Run `yarn prebuild` and `yarn ios` and build the app!
|
||||
|
||||
## Go-Server Build
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Go](https://go.dev/)
|
||||
- [Yarn](https://yarnpkg.com/)
|
||||
|
||||
### Steps
|
||||
|
||||
To run the build with Go, use staging credentials, your own, or any other account you create.
|
||||
|
||||
```
|
||||
cd social-app
|
||||
yarn && yarn build-web
|
||||
cp ./web-build/static/js/*.* bskyweb/static/js/
|
||||
cd bskyweb/
|
||||
go mod tidy
|
||||
go build -v -tags timetzdata -o bskyweb ./cmd/bskyweb
|
||||
./bskyweb serve --pds-host=https://staging.bsky.dev --handle=<HANDLE> --password=<PASSWORD>
|
||||
```
|
||||
|
||||
On build success, access the application at [http://localhost:8100/](http://localhost:8100/). Subsequent changes require re-running the above steps in order to be reflected.
|
||||
|
||||
## Various notes
|
||||
|
||||
### Debugging
|
||||
|
||||
- Note that since 0.70, debugging using the old debugger (which shows up using CMD+D) doesn't work anymore. Follow the instructions below to debug the code: https://reactnative.dev/docs/next/hermes#debugging-js-on-hermes-using-google-chromes-devtools
|
||||
|
||||
### Developer Menu
|
||||
|
||||
To open the [Developer Menu](https://docs.expo.dev/debugging/tools/#developer-menu) on an `expo-dev-client` app you can do the following:
|
||||
|
||||
- Android Device: Shake the device vertically, or if your device is connected via USB, run adb shell input keyevent 82 in your terminal
|
||||
- Android Emulator: Either press Cmd ⌘ + m or Ctrl + m or run adb shell input keyevent 82 in your terminal
|
||||
- iOS Device: Shake the device, or touch 3 fingers to the screen
|
||||
- iOS Simulator: Press Ctrl + Cmd ⌘ + z on a Mac in the emulator to simulate the shake gesture, or press Cmd ⌘ + d
|
||||
|
||||
### Running E2E Tests
|
||||
|
||||
- Make sure you've setup your environment following above
|
||||
- Make sure Metro and the dev server are running
|
||||
- Run `yarn e2e`
|
||||
- Find the artifacts in the `artifact` folder
|
||||
|
||||
### Polyfills
|
||||
|
||||
`./platform/polyfills.*.ts` adds polyfills to the environment. Currently this includes:
|
||||
|
||||
- TextEncoder / TextDecoder
|
||||
|
||||
### Sentry sourcemaps
|
||||
|
||||
Sourcemaps should automatically be updated when a signed build is created using `eas build` and published using `eas submit` due to the postPublish hook setup in `app.json`. However, if an update is created and published OTA using `eas update`, we need to the take the following steps to upload sourcemaps to Sentry:
|
||||
|
||||
- Run eas update. This will generate a dist folder in your project root, which contains your JavaScript bundles and source maps. This command will also output the 'Android update ID' and 'iOS update ID' that we'll need in the next step.
|
||||
- Copy or rename the bundle names in the `dist/bundles` folder to match `index.android.bundle` (Android) or `main.jsbundle` (iOS).
|
||||
- Next, you can use the Sentry CLI to upload your bundles and source maps:
|
||||
- release name should be set to `${bundleIdentifier}@${version}+${buildNumber}` (iOS) or `${androidPackage}@${version}+${versionCode}` (Android), so for example `com.domain.myapp@1.0.0+1`.
|
||||
- `dist` should be set to the Update ID that `eas update` generated.
|
||||
- Command for Android:
|
||||
`node_modules/@sentry/cli/bin/sentry-cli releases \
|
||||
files <release name> \
|
||||
upload-sourcemaps \
|
||||
--dist <Android Update ID> \
|
||||
--rewrite \
|
||||
dist/bundles/index.android.bundle dist/bundles/android-<hash>.map`
|
||||
- Command for iOS:
|
||||
`node_modules/@sentry/cli/bin/sentry-cli releases \
|
||||
files <release name> \
|
||||
upload-sourcemaps \
|
||||
--dist <iOS Update ID> \
|
||||
--rewrite \
|
||||
dist/bundles/main.jsbundle dist/bundles/ios-<hash>.map`
|
||||
|
||||
### OTA updates
|
||||
To create OTA updates, run `eas update` along with the `--branch` flag to indicate which branch you want to push the update to, and the `--message` flag to indicate a message for yourself and your team that shows up on https://expo.dev. ALl the channels (which make up the options for the `--branch` flag) are given in `eas.json`. [See more here](https://docs.expo.dev/eas-update/getting-started/)
|
||||
|
||||
The clients which can receive an OTA update is governed by the `runtimeVersion` property in `app.json`. Right now, it is set so that only apps with the same `appVersion` (same as `version` property in `app.json`) can receive the update and install it. However, we can manually set `"runtimeVersion": "1.34.0"` or anything along those lines as well. This is useful if very little native code changes from update-to-update. If we are manually setting `runtimeVersion`, we should increment the version each time native code is changed. [See more here](https://docs.expo.dev/eas-update/runtime-versions/)
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"cli": {
|
||||
"version": ">= 3.8.1",
|
||||
"promptToConfigurePushNotifications": false
|
||||
},
|
||||
"build": {
|
||||
"development": {
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"ios": {
|
||||
"simulator": true,
|
||||
"resourceClass": "medium"
|
||||
},
|
||||
"channel": "development"
|
||||
},
|
||||
"preview": {
|
||||
"distribution": "internal",
|
||||
"ios": {
|
||||
"resourceClass": "medium"
|
||||
},
|
||||
"channel": "preview"
|
||||
},
|
||||
"production": {
|
||||
"ios": {
|
||||
"resourceClass": "medium"
|
||||
},
|
||||
"channel": "production"
|
||||
}
|
||||
},
|
||||
"submit": {
|
||||
"production": {}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -0,0 +1 @@
|
||||
export NODE_BINARY="/Users/paulfrazee/.nvm/versions/node/v18.8.0/bin/node"
|
||||
@@ -0,0 +1,100 @@
|
||||
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
|
||||
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
|
||||
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")
|
||||
|
||||
require 'json'
|
||||
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
|
||||
|
||||
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
|
||||
|
||||
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.0'
|
||||
install! 'cocoapods',
|
||||
:deterministic_uuids => false
|
||||
|
||||
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,...), which will be excluded. To fix this,
|
||||
# you can also exclude `react-native-flipper` in `react-native.config.js`
|
||||
#
|
||||
# ```js
|
||||
# module.exports = {
|
||||
# dependencies: {
|
||||
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
|
||||
# }
|
||||
# }
|
||||
# ```
|
||||
flipper_config = FlipperConfiguration.disabled
|
||||
if ENV['NO_FLIPPER'] == "1" || ENV['CI'] then
|
||||
# Explicitly disabled through environment variables
|
||||
flipper_config = FlipperConfiguration.disabled
|
||||
elsif podfile_properties.key?('ios.flipper') then
|
||||
# Configure Flipper in Podfile.properties.json
|
||||
if podfile_properties['ios.flipper'] == 'true' then
|
||||
flipper_config = FlipperConfiguration.enabled(["Debug", "Release"])
|
||||
elsif ppodfile_properties['ios.flipper'] != 'false' then
|
||||
flipper_config = FlipperConfiguration.enabled(["Debug", "Release"], { 'Flipper' => podfile_properties['ios.flipper'] })
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'bluesky' do
|
||||
use_expo_modules!
|
||||
config = use_native_modules!
|
||||
|
||||
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
||||
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
||||
|
||||
# Flags change depending on the env values.
|
||||
flags = get_default_flags()
|
||||
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
|
||||
:fabric_enabled => flags[:fabric_enabled],
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/..",
|
||||
# Note that if you have use_frameworks! enabled, Flipper will not work if enabled
|
||||
:flipper_configuration => flipper_config
|
||||
)
|
||||
|
||||
post_install do |installer|
|
||||
react_native_post_install(
|
||||
installer,
|
||||
config[:reactNativePath],
|
||||
# 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)
|
||||
|
||||
# Required to force the pods to use the correct deploy version
|
||||
# See https://github.com/facebook/react-native/issues/34106
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['SWIFT_VERSION'] = '5.0'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
|
||||
end
|
||||
end
|
||||
|
||||
# This is necessary for Xcode 14, because it signs resource bundles by default
|
||||
# when building for devices.
|
||||
installer.target_installation_results.pod_target_installation_results
|
||||
.each do |pod_name, target_installation_result|
|
||||
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
|
||||
resource_bundle_target.build_configurations.each do |config|
|
||||
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
post_integrate do |installer|
|
||||
begin
|
||||
expo_patch_react_imports!(installer)
|
||||
rescue => e
|
||||
Pod::UI.warn e
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,922 @@
|
||||
PODS:
|
||||
- boost (1.76.0)
|
||||
- BVLinearGradient (2.6.2):
|
||||
- React-Core
|
||||
- DoubleConversion (1.1.6)
|
||||
- EXApplication (5.1.1):
|
||||
- ExpoModulesCore
|
||||
- EXCamera (13.2.1):
|
||||
- ExpoModulesCore
|
||||
- EXConstants (14.2.1):
|
||||
- ExpoModulesCore
|
||||
- EXFileSystem (15.2.2):
|
||||
- ExpoModulesCore
|
||||
- EXFont (11.1.1):
|
||||
- ExpoModulesCore
|
||||
- EXImageLoader (4.1.1):
|
||||
- ExpoModulesCore
|
||||
- React-Core
|
||||
- EXJSONUtils (0.5.1)
|
||||
- EXManifests (0.5.2):
|
||||
- EXJSONUtils
|
||||
- EXMediaLibrary (15.2.3):
|
||||
- ExpoModulesCore
|
||||
- React-Core
|
||||
- Expo (48.0.9):
|
||||
- ExpoModulesCore
|
||||
- expo-dev-client (2.1.5):
|
||||
- EXManifests
|
||||
- expo-dev-launcher
|
||||
- expo-dev-menu
|
||||
- expo-dev-menu-interface
|
||||
- EXUpdatesInterface
|
||||
- expo-dev-launcher (2.1.5):
|
||||
- EXManifests
|
||||
- expo-dev-launcher/Main (= 2.1.5)
|
||||
- expo-dev-menu
|
||||
- expo-dev-menu-interface
|
||||
- ExpoModulesCore
|
||||
- EXUpdatesInterface
|
||||
- React-Core
|
||||
- expo-dev-launcher/Main (2.1.5):
|
||||
- EXManifests
|
||||
- expo-dev-launcher/Unsafe
|
||||
- expo-dev-menu
|
||||
- expo-dev-menu-interface
|
||||
- ExpoModulesCore
|
||||
- EXUpdatesInterface
|
||||
- React-Core
|
||||
- expo-dev-launcher/Unsafe (2.1.5):
|
||||
- EXManifests
|
||||
- expo-dev-menu
|
||||
- expo-dev-menu-interface
|
||||
- ExpoModulesCore
|
||||
- EXUpdatesInterface
|
||||
- React-Core
|
||||
- expo-dev-menu (2.1.3):
|
||||
- expo-dev-menu/Main (= 2.1.3)
|
||||
- expo-dev-menu-interface (1.1.1)
|
||||
- expo-dev-menu/GestureHandler (2.1.3)
|
||||
- expo-dev-menu/Main (2.1.3):
|
||||
- EXManifests
|
||||
- expo-dev-menu-interface
|
||||
- expo-dev-menu/Vendored
|
||||
- ExpoModulesCore
|
||||
- React-Core
|
||||
- expo-dev-menu/Reanimated (2.1.3):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
- glog
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-callinvoker
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-Core/RCTWebSocket
|
||||
- React-CoreModules
|
||||
- React-cxxreact
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-jsinspector
|
||||
- React-RCTActionSheet
|
||||
- React-RCTAnimation
|
||||
- React-RCTBlob
|
||||
- React-RCTImage
|
||||
- React-RCTLinking
|
||||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- React-RCTVibration
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- expo-dev-menu/SafeAreaView (2.1.3)
|
||||
- expo-dev-menu/Vendored (2.1.3):
|
||||
- expo-dev-menu/GestureHandler
|
||||
- expo-dev-menu/Reanimated
|
||||
- expo-dev-menu/SafeAreaView
|
||||
- ExpoImagePicker (14.1.1):
|
||||
- ExpoModulesCore
|
||||
- ExpoKeepAwake (12.0.1):
|
||||
- ExpoModulesCore
|
||||
- ExpoLocalization (14.1.1):
|
||||
- ExpoModulesCore
|
||||
- ExpoModulesCore (1.2.6):
|
||||
- React-Core
|
||||
- React-RCTAppDelegate
|
||||
- ReactCommon/turbomodule/core
|
||||
- EXSplashScreen (0.18.1):
|
||||
- ExpoModulesCore
|
||||
- React-Core
|
||||
- EXUpdatesInterface (0.9.1)
|
||||
- FBLazyVector (0.71.4)
|
||||
- FBReactNativeSpec (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.4)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Core (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- fmt (6.2.1)
|
||||
- glog (0.3.5)
|
||||
- hermes-engine (0.71.4):
|
||||
- hermes-engine/Pre-built (= 0.71.4)
|
||||
- hermes-engine/Pre-built (0.71.4)
|
||||
- libevent (2.1.12)
|
||||
- libwebp (1.2.4):
|
||||
- libwebp/demux (= 1.2.4)
|
||||
- libwebp/mux (= 1.2.4)
|
||||
- libwebp/webp (= 1.2.4)
|
||||
- libwebp/demux (1.2.4):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.2.4):
|
||||
- libwebp/demux
|
||||
- libwebp/webp (1.2.4)
|
||||
- RCT-Folly (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Default (= 2021.07.22.00)
|
||||
- RCT-Folly/Default (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Futures (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- libevent
|
||||
- RCTRequired (0.71.4)
|
||||
- RCTTypeSafety (0.71.4):
|
||||
- FBLazyVector (= 0.71.4)
|
||||
- RCTRequired (= 0.71.4)
|
||||
- React-Core (= 0.71.4)
|
||||
- React (0.71.4):
|
||||
- React-Core (= 0.71.4)
|
||||
- React-Core/DevSupport (= 0.71.4)
|
||||
- React-Core/RCTWebSocket (= 0.71.4)
|
||||
- React-RCTActionSheet (= 0.71.4)
|
||||
- React-RCTAnimation (= 0.71.4)
|
||||
- React-RCTBlob (= 0.71.4)
|
||||
- React-RCTImage (= 0.71.4)
|
||||
- React-RCTLinking (= 0.71.4)
|
||||
- React-RCTNetwork (= 0.71.4)
|
||||
- React-RCTSettings (= 0.71.4)
|
||||
- React-RCTText (= 0.71.4)
|
||||
- React-RCTVibration (= 0.71.4)
|
||||
- React-callinvoker (0.71.4)
|
||||
- React-Codegen (0.71.4):
|
||||
- FBReactNativeSpec
|
||||
- hermes-engine
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-Core (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.4)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/Default (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.4)
|
||||
- React-Core/RCTWebSocket (= 0.71.4)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-jsinspector (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.71.4):
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.4)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-hermes
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- Yoga
|
||||
- React-CoreModules (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/CoreModulesHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-RCTBlob
|
||||
- React-RCTImage (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-cxxreact (0.71.4):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-jsinspector (= 0.71.4)
|
||||
- React-logger (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- React-runtimeexecutor (= 0.71.4)
|
||||
- React-hermes (0.71.4):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCT-Folly/Futures (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-jsi
|
||||
- React-jsiexecutor (= 0.71.4)
|
||||
- React-jsinspector (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- React-jsi (0.71.4):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsiexecutor (0.71.4):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- React-jsinspector (0.71.4)
|
||||
- React-logger (0.71.4):
|
||||
- glog
|
||||
- react-native-blur (4.3.0):
|
||||
- React-Core
|
||||
- react-native-cameraroll (5.3.1):
|
||||
- React-Core
|
||||
- react-native-get-random-values (1.8.0):
|
||||
- React-Core
|
||||
- react-native-image-resizer (3.0.5):
|
||||
- React-Core
|
||||
- react-native-pager-view (6.1.2):
|
||||
- React-Core
|
||||
- react-native-paste-input (0.6.2):
|
||||
- React-Core
|
||||
- Swime (= 3.0.6)
|
||||
- react-native-safe-area-context (4.5.0):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- react-native-splash-screen (3.3.0):
|
||||
- React-Core
|
||||
- react-native-version-number (0.3.6):
|
||||
- React
|
||||
- React-perflogger (0.71.4)
|
||||
- React-RCTActionSheet (0.71.4):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.71.4)
|
||||
- React-RCTAnimation (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTAnimationHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTAppDelegate (0.71.4):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-RCTBlob (0.71.4):
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTBlobHeaders (= 0.71.4)
|
||||
- React-Core/RCTWebSocket (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-RCTNetwork (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTImage (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTImageHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-RCTNetwork (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTLinking (0.71.4):
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTLinkingHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTNetwork (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTNetworkHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTSettings (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.4)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTSettingsHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-RCTText (0.71.4):
|
||||
- React-Core/RCTTextHeaders (= 0.71.4)
|
||||
- React-RCTVibration (0.71.4):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.71.4)
|
||||
- React-Core/RCTVibrationHeaders (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (= 0.71.4)
|
||||
- React-runtimeexecutor (0.71.4):
|
||||
- React-jsi (= 0.71.4)
|
||||
- ReactCommon/turbomodule/bridging (0.71.4):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.4)
|
||||
- React-Core (= 0.71.4)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-logger (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- ReactCommon/turbomodule/core (0.71.4):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.71.4)
|
||||
- React-Core (= 0.71.4)
|
||||
- React-cxxreact (= 0.71.4)
|
||||
- React-jsi (= 0.71.4)
|
||||
- React-logger (= 0.71.4)
|
||||
- React-perflogger (= 0.71.4)
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNBackgroundFetch (4.1.9):
|
||||
- React-Core
|
||||
- RNCAsyncStorage (1.17.12):
|
||||
- React-Core
|
||||
- RNCClipboard (1.11.2):
|
||||
- React-Core
|
||||
- RNFastImage (8.6.3):
|
||||
- React-Core
|
||||
- SDWebImage (~> 5.11.1)
|
||||
- SDWebImageWebPCoder (~> 0.8.4)
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.9.0):
|
||||
- React-Core
|
||||
- RNImageCropPicker (0.38.1):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNImageCropPicker/QBImagePickerController (= 0.38.1)
|
||||
- TOCropViewController
|
||||
- RNImageCropPicker/QBImagePickerController (0.38.1):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- TOCropViewController
|
||||
- RNInAppBrowser (3.7.0):
|
||||
- React-Core
|
||||
- RNNotifee (7.6.1):
|
||||
- React-Core
|
||||
- RNNotifee/NotifeeCore (= 7.6.1)
|
||||
- RNNotifee/NotifeeCore (7.6.1):
|
||||
- React-Core
|
||||
- RNReactNativeHapticFeedback (1.14.0):
|
||||
- React-Core
|
||||
- RNReanimated (2.14.4):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
- glog
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-callinvoker
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-Core/RCTWebSocket
|
||||
- React-CoreModules
|
||||
- React-cxxreact
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-jsinspector
|
||||
- React-RCTActionSheet
|
||||
- React-RCTAnimation
|
||||
- React-RCTBlob
|
||||
- React-RCTImage
|
||||
- React-RCTLinking
|
||||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNScreens (3.20.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNSVG (13.4.0):
|
||||
- React-Core
|
||||
- SDWebImage (5.11.1):
|
||||
- SDWebImage/Core (= 5.11.1)
|
||||
- SDWebImage/Core (5.11.1)
|
||||
- SDWebImageWebPCoder (0.8.5):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.10)
|
||||
- segment-analytics-react-native (2.13.4):
|
||||
- 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)
|
||||
|
||||
DEPENDENCIES:
|
||||
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
|
||||
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- EXApplication (from `../node_modules/expo-application/ios`)
|
||||
- EXCamera (from `../node_modules/expo-camera/ios`)
|
||||
- EXConstants (from `../node_modules/expo-constants/ios`)
|
||||
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
|
||||
- EXFont (from `../node_modules/expo-font/ios`)
|
||||
- EXImageLoader (from `../node_modules/expo-image-loader/ios`)
|
||||
- EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
|
||||
- EXManifests (from `../node_modules/expo-manifests/ios`)
|
||||
- EXMediaLibrary (from `../node_modules/expo-media-library/ios`)
|
||||
- Expo (from `../node_modules/expo`)
|
||||
- expo-dev-client (from `../node_modules/expo-dev-client/ios`)
|
||||
- expo-dev-launcher (from `../node_modules/expo-dev-launcher`)
|
||||
- expo-dev-menu (from `../node_modules/expo-dev-menu`)
|
||||
- expo-dev-menu-interface (from `../node_modules/expo-dev-menu-interface/ios`)
|
||||
- ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
|
||||
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
|
||||
- ExpoLocalization (from `../node_modules/expo-localization/ios`)
|
||||
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
|
||||
- EXSplashScreen (from `../node_modules/expo-splash-screen/ios`)
|
||||
- EXUpdatesInterface (from `../node_modules/expo-updates-interface/ios`)
|
||||
- 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`)
|
||||
- React (from `../node_modules/react-native/`)
|
||||
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
|
||||
- React-Codegen (from `build/generated/ios`)
|
||||
- React-Core (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-get-random-values (from `../node_modules/react-native-get-random-values`)
|
||||
- "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`)
|
||||
- React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
|
||||
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
|
||||
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
|
||||
- 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`)"
|
||||
- RNFastImage (from `../node_modules/react-native-fast-image`)
|
||||
- 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
|
||||
- libwebp
|
||||
- SDWebImage
|
||||
- SDWebImageWebPCoder
|
||||
- Swime
|
||||
- TOCropViewController
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
boost:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
|
||||
BVLinearGradient:
|
||||
:path: "../node_modules/react-native-linear-gradient"
|
||||
DoubleConversion:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||
EXApplication:
|
||||
:path: "../node_modules/expo-application/ios"
|
||||
EXCamera:
|
||||
:path: "../node_modules/expo-camera/ios"
|
||||
EXConstants:
|
||||
:path: "../node_modules/expo-constants/ios"
|
||||
EXFileSystem:
|
||||
:path: "../node_modules/expo-file-system/ios"
|
||||
EXFont:
|
||||
:path: "../node_modules/expo-font/ios"
|
||||
EXImageLoader:
|
||||
:path: "../node_modules/expo-image-loader/ios"
|
||||
EXJSONUtils:
|
||||
:path: "../node_modules/expo-json-utils/ios"
|
||||
EXManifests:
|
||||
:path: "../node_modules/expo-manifests/ios"
|
||||
EXMediaLibrary:
|
||||
:path: "../node_modules/expo-media-library/ios"
|
||||
Expo:
|
||||
:path: "../node_modules/expo"
|
||||
expo-dev-client:
|
||||
:path: "../node_modules/expo-dev-client/ios"
|
||||
expo-dev-launcher:
|
||||
:path: "../node_modules/expo-dev-launcher"
|
||||
expo-dev-menu:
|
||||
:path: "../node_modules/expo-dev-menu"
|
||||
expo-dev-menu-interface:
|
||||
:path: "../node_modules/expo-dev-menu-interface/ios"
|
||||
ExpoImagePicker:
|
||||
:path: "../node_modules/expo-image-picker/ios"
|
||||
ExpoKeepAwake:
|
||||
:path: "../node_modules/expo-keep-awake/ios"
|
||||
ExpoLocalization:
|
||||
:path: "../node_modules/expo-localization/ios"
|
||||
ExpoModulesCore:
|
||||
:path: "../node_modules/expo-modules-core"
|
||||
EXSplashScreen:
|
||||
:path: "../node_modules/expo-splash-screen/ios"
|
||||
EXUpdatesInterface:
|
||||
:path: "../node_modules/expo-updates-interface/ios"
|
||||
FBLazyVector:
|
||||
:path: "../node_modules/react-native/Libraries/FBLazyVector"
|
||||
FBReactNativeSpec:
|
||||
: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:
|
||||
:path: "../node_modules/react-native/Libraries/RCTRequired"
|
||||
RCTTypeSafety:
|
||||
:path: "../node_modules/react-native/Libraries/TypeSafety"
|
||||
React:
|
||||
:path: "../node_modules/react-native/"
|
||||
React-callinvoker:
|
||||
:path: "../node_modules/react-native/ReactCommon/callinvoker"
|
||||
React-Codegen:
|
||||
:path: build/generated/ios
|
||||
React-Core:
|
||||
:path: "../node_modules/react-native/"
|
||||
React-CoreModules:
|
||||
: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:
|
||||
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
|
||||
React-jsinspector:
|
||||
: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-get-random-values:
|
||||
:path: "../node_modules/react-native-get-random-values"
|
||||
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:
|
||||
:path: "../node_modules/react-native-splash-screen"
|
||||
react-native-version-number:
|
||||
:path: "../node_modules/react-native-version-number"
|
||||
React-perflogger:
|
||||
:path: "../node_modules/react-native/ReactCommon/reactperflogger"
|
||||
React-RCTActionSheet:
|
||||
: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:
|
||||
:path: "../node_modules/react-native/Libraries/Image"
|
||||
React-RCTLinking:
|
||||
:path: "../node_modules/react-native/Libraries/LinkingIOS"
|
||||
React-RCTNetwork:
|
||||
:path: "../node_modules/react-native/Libraries/Network"
|
||||
React-RCTSettings:
|
||||
:path: "../node_modules/react-native/Libraries/Settings"
|
||||
React-RCTText:
|
||||
:path: "../node_modules/react-native/Libraries/Text"
|
||||
React-RCTVibration:
|
||||
:path: "../node_modules/react-native/Libraries/Vibration"
|
||||
React-runtimeexecutor:
|
||||
: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"
|
||||
RNFastImage:
|
||||
:path: "../node_modules/react-native-fast-image"
|
||||
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"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost: 57d2868c099736d80fcd648bf211b4431e51a558
|
||||
BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
EXApplication: d8f53a7eee90a870a75656280e8d4b85726ea903
|
||||
EXCamera: a323a5942b5e7fc8349e17d728e91c18840ad561
|
||||
EXConstants: f348da07e21b23d2b085e270d7b74f282df1a7d9
|
||||
EXFileSystem: 844e86ca9b5375486ecc4ef06d3838d5597d895d
|
||||
EXFont: 6ea3800df746be7233208d80fe379b8ed74f4272
|
||||
EXImageLoader: fd053169a8ee932dd83bf1fe5487a50c26d27c2b
|
||||
EXJSONUtils: 48b1e764ac35160e6f54d21ab60d7d9501f3e473
|
||||
EXManifests: 500666d48e8dd7ca5a482c9e729e4a7a6c34081b
|
||||
EXMediaLibrary: 587cd8aad27a6fc8d7c38b950bc75bc1845a7480
|
||||
Expo: 863488a600a4565698a79577117c70b170054d08
|
||||
expo-dev-client: 7c1ef51516853465f4d448c14ddf365167d20361
|
||||
expo-dev-launcher: 90de99d9e5d1a883d81355ca10e87c2f3c81d46e
|
||||
expo-dev-menu: 4f54ef98df59d9d625677cb18ad4582de92b4a7d
|
||||
expo-dev-menu-interface: 6c82ae323c4b8724dead4763ce3ff24a2108bdb1
|
||||
ExpoImagePicker: 270dea232b3a072d981dd564e2cafc63a864edb1
|
||||
ExpoKeepAwake: 69f5f627670d62318410392d03e0b5db0f85759a
|
||||
ExpoLocalization: f26cd431ad9ea3533c5b08c4fabd879176a794bb
|
||||
ExpoModulesCore: 6e0259511f4c4341b6b8357db393624df2280828
|
||||
EXSplashScreen: cd7fb052dff5ba8311d5c2455ecbebffe1b7a8ca
|
||||
EXUpdatesInterface: dd699d1930e28639dcbd70a402caea98e86364ca
|
||||
FBLazyVector: 446e84642979fff0ba57f3c804c2228a473aeac2
|
||||
FBReactNativeSpec: 241709e132e3bf1526c1c4f00bc5384dd39dfba9
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
hermes-engine: a1f157c49ea579c28b0296bda8530e980c45bdb3
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||
RCTRequired: 5a024fdf458fa8c0d82fc262e76f982d4dcdecdd
|
||||
RCTTypeSafety: b6c253064466411c6810b45f66bc1e43ce0c54ba
|
||||
React: 715292db5bd46989419445a5547954b25d2090f0
|
||||
React-callinvoker: 105392d1179058585b564d35b4592fe1c46d6fba
|
||||
React-Codegen: b75333b93d835afce84b73472927cccaef2c9f8c
|
||||
React-Core: 88838ed1724c64905fc6c0811d752828a92e395b
|
||||
React-CoreModules: cd238b4bb8dc8529ccc8b34ceae7267b04ce1882
|
||||
React-cxxreact: 291bfab79d8098dc5ebab98f62e6bdfe81b3955a
|
||||
React-hermes: b1e67e9a81c71745704950516f40ee804349641c
|
||||
React-jsi: c9d5b563a6af6bb57034a82c2b0d39d0a7483bdc
|
||||
React-jsiexecutor: d6b7fa9260aa3cb40afee0507e3bc1d17ecaa6f2
|
||||
React-jsinspector: 1f51e775819199d3fe9410e69ee8d4c4161c7b06
|
||||
React-logger: 0d58569ec51d30d1792c5e86a8e3b78d24b582c6
|
||||
react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
|
||||
react-native-cameraroll: f3050460fe1708378698c16686bfaa5f34099be2
|
||||
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
|
||||
react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa
|
||||
react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43
|
||||
react-native-paste-input: 3392800944a47c00dddbff23c31c281482209679
|
||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-version-number: b415bbec6a13f2df62bf978e85bc0d699462f37f
|
||||
React-perflogger: 0bb0522a12e058f6eb69d888bc16f40c16c4b907
|
||||
React-RCTActionSheet: bfd675a10f06a18728ea15d82082d48f228a213a
|
||||
React-RCTAnimation: 2fa220b2052ec75b733112aca39143d34546a941
|
||||
React-RCTAppDelegate: 8564f93c1d9274e95e3b0c746d08a87ff5a621b2
|
||||
React-RCTBlob: d0336111f46301ae8aba2e161817e451aad72dd6
|
||||
React-RCTImage: fec592c46edb7c12a9cde08780bdb4a688416c62
|
||||
React-RCTLinking: 14eccac5d2a3b34b89dbfa29e8ef6219a153fe2d
|
||||
React-RCTNetwork: 1fbce92e772e39ca3687a2ebb854501ff6226dd7
|
||||
React-RCTSettings: 1abea36c9bb16d9979df6c4b42e2ea281b4bbcc5
|
||||
React-RCTText: 15355c41561a9f43dfd23616d0a0dd40ba05ed61
|
||||
React-RCTVibration: ad17efcfb2fa8f6bfd8ac0cf48d96668b8b28e0b
|
||||
React-runtimeexecutor: 8fa50b38df6b992c76537993a2b0553d3b088004
|
||||
ReactCommon: b49a4b00ca6d181ff74b17c12b2d59ac4add0bde
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNBackgroundFetch: 642777e4e76435773c149d565a043d66f1781237
|
||||
RNCAsyncStorage: 09fc8595e6d6f6d5abf16b23a56b257d9c6b7c5b
|
||||
RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc
|
||||
RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||
RNImageCropPicker: 648356d68fbf9911a1016b3e3723885d28373eda
|
||||
RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364
|
||||
RNNotifee: bdc064c29f4d558046f51f0c3ae02bab4fd3cd85
|
||||
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
|
||||
RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128
|
||||
RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
|
||||
RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
|
||||
segment-analytics-react-native: cc12d9422f7ce863ee57c1b650ab48eec4b6d5bd
|
||||
sovran-react-native: fd3dc8f1a4b14acdc4ad25fc6b4ac4f52a2a2a15
|
||||
Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b
|
||||
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
||||
Yoga: 79dd7410de6f8ad73a77c868d3d368843f0c93e0
|
||||
|
||||
PODFILE CHECKSUM: a70ccad2941a86bea1bc3ed0f6cb08a564cf7910
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"expo.jsEngine": "hermes"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,66 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
#define TIMEOUT_SECONDS 600
|
||||
#define TEXT_TO_LOOK_FOR @"Welcome to React"
|
||||
|
||||
@interface appTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation appTests
|
||||
|
||||
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
|
||||
{
|
||||
if (test(view)) {
|
||||
return YES;
|
||||
}
|
||||
for (UIView *subview in [view subviews]) {
|
||||
if ([self findSubviewInView:subview matching:test]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)testRendersWelcomeScreen
|
||||
{
|
||||
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
BOOL foundElement = NO;
|
||||
|
||||
__block NSString *redboxError = nil;
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(
|
||||
^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||
if (level >= RCTLogLevelError) {
|
||||
redboxError = message;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
|
||||
foundElement = [self findSubviewInView:vc.view
|
||||
matching:^BOOL(UIView *view) {
|
||||
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(RCTDefaultLogFunction);
|
||||
#endif
|
||||
|
||||
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
||||
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,543 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 53;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
14F1D8D19D7FBF5995C9B32D /* libPods-bluesky.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B74BD82B16D3B7F19E5ADDA /* libPods-bluesky.a */; };
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
|
||||
B6BE37E812824A869C1E16F6 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FECE0FEBF1E4D88B437323C /* noop-file.swift */; };
|
||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
||||
11FD9D89D32941D7ECE26520 /* Pods-bluesky.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-bluesky.debug.xcconfig"; path = "Target Support Files/Pods-bluesky/Pods-bluesky.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* bluesky.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bluesky.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = bluesky/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = bluesky/AppDelegate.mm; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = bluesky/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = bluesky/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = bluesky/main.m; sourceTree = "<group>"; };
|
||||
4FECE0FEBF1E4D88B437323C /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "bluesky/noop-file.swift"; sourceTree = "<group>"; };
|
||||
5B74BD82B16D3B7F19E5ADDA /* libPods-bluesky.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-bluesky.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = bluesky/SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
||||
C92ECE114C152498B9DF0C14 /* Pods-bluesky.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-bluesky.release.xcconfig"; path = "Target Support Files/Pods-bluesky/Pods-bluesky.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-bluesky/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14F1D8D19D7FBF5995C9B32D /* libPods-bluesky.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13B07FAE1A68108700A75B9A /* bluesky */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB2F792B24A3F905000567C9 /* Supporting */,
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
|
||||
4FECE0FEBF1E4D88B437323C /* noop-file.swift */,
|
||||
);
|
||||
name = bluesky;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
5B74BD82B16D3B7F19E5ADDA /* libPods-bluesky.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* bluesky */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
D65327D7A22EEC0BE12398D9 /* Pods */,
|
||||
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* bluesky.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92DBD88DE9BF7D494EA9DA96 /* bluesky */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
|
||||
);
|
||||
name = bluesky;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BB2F792B24A3F905000567C9 /* Supporting */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB2F792C24A3F905000567C9 /* Expo.plist */,
|
||||
);
|
||||
name = Supporting;
|
||||
path = bluesky/Supporting;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D65327D7A22EEC0BE12398D9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
11FD9D89D32941D7ECE26520 /* Pods-bluesky.debug.xcconfig */,
|
||||
C92ECE114C152498B9DF0C14 /* Pods-bluesky.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92DBD88DE9BF7D494EA9DA96 /* bluesky */,
|
||||
);
|
||||
name = ExpoModulesProviders;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* bluesky */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "bluesky" */;
|
||||
buildPhases = (
|
||||
AA58FC21F429DA1C08D4849A /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
5555462490F6788D569DDAFD /* [CP] Embed Pods Frameworks */,
|
||||
D9DEAD65B781F987C1B90893 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = bluesky;
|
||||
productName = bluesky;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* bluesky.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1430;
|
||||
TargetAttributes = {
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
DevelopmentTeam = B3LX46C5HS;
|
||||
LastSwiftMigration = 1250;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "bluesky" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* bluesky */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" $PROJECT_ROOT ios relative | tail -n 1)\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
|
||||
};
|
||||
5555462490F6788D569DDAFD /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-bluesky/Pods-bluesky-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-bluesky/Pods-bluesky-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
AA58FC21F429DA1C08D4849A /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-bluesky-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
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;
|
||||
};
|
||||
D9DEAD65B781F987C1B90893 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-bluesky/Pods-bluesky-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-bluesky/Pods-bluesky-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Start Packager";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\nexport RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
|
||||
B6BE37E812824A869C1E16F6 /* noop-file.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 11FD9D89D32941D7ECE26520 /* Pods-bluesky.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = bluesky/bluesky.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = B3LX46C5HS;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"FB_SONARKIT_ENABLED=1",
|
||||
);
|
||||
INFOPLIST_FILE = bluesky/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.blueskyweb.app;
|
||||
PRODUCT_NAME = bluesky;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C92ECE114C152498B9DF0C14 /* Pods-bluesky.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = bluesky/bluesky.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = B3LX46C5HS;
|
||||
INFOPLIST_FILE = bluesky/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.blueskyweb.app;
|
||||
PRODUCT_NAME = bluesky;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "bluesky" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "bluesky" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "bluesky.app"
|
||||
BlueprintName = "bluesky"
|
||||
ReferencedContainer = "container:bluesky.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "blueskyTests.xctest"
|
||||
BlueprintName = "blueskyTests"
|
||||
ReferencedContainer = "container:bluesky.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "bluesky.app"
|
||||
BlueprintName = "bluesky"
|
||||
ReferencedContainer = "container:bluesky.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "bluesky.app"
|
||||
BlueprintName = "bluesky"
|
||||
ReferencedContainer = "container:bluesky.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:bluesky.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,7 @@
|
||||
#import <RCTAppDelegate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Expo/Expo.h>
|
||||
|
||||
@interface AppDelegate : EXAppDelegateWrapper
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,72 @@
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
#import <React/RCTLinkingManager.h>
|
||||
|
||||
#import <TSBackgroundFetch/TSBackgroundFetch.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.moduleName = @"main";
|
||||
|
||||
// You can add your custom initial props in the dictionary below.
|
||||
// They will be passed down to the ViewController used by React Native.
|
||||
self.initialProps = @{};
|
||||
|
||||
// Register BackgroundFetch
|
||||
[[TSBackgroundFetch sharedInstance] didFinishLaunching];
|
||||
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||
{
|
||||
#if DEBUG
|
||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
||||
#else
|
||||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// 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
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Linking API
|
||||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||
return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
|
||||
}
|
||||
|
||||
// Universal Links
|
||||
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
|
||||
BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
|
||||
return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
|
||||
}
|
||||
|
||||
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
|
||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||
{
|
||||
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
||||
}
|
||||
|
||||
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
|
||||
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||
{
|
||||
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
|
||||
}
|
||||
|
||||
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
|
||||
{
|
||||
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
|
||||
}
|
||||
|
||||
@end
|
||||
|
After Width: | Height: | Size: 966 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "20x20",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "20x20",
|
||||
"scale": "3x",
|
||||
"filename": "App-Icon-20x20@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "29x29",
|
||||
"scale": "1x",
|
||||
"filename": "App-Icon-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "29x29",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "29x29",
|
||||
"scale": "3x",
|
||||
"filename": "App-Icon-29x29@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "40x40",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "40x40",
|
||||
"scale": "3x",
|
||||
"filename": "App-Icon-40x40@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "60x60",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-60x60@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone",
|
||||
"size": "60x60",
|
||||
"scale": "3x",
|
||||
"filename": "App-Icon-60x60@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "20x20",
|
||||
"scale": "1x",
|
||||
"filename": "App-Icon-20x20@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "20x20",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "29x29",
|
||||
"scale": "1x",
|
||||
"filename": "App-Icon-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "29x29",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "40x40",
|
||||
"scale": "1x",
|
||||
"filename": "App-Icon-40x40@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "40x40",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "76x76",
|
||||
"scale": "1x",
|
||||
"filename": "App-Icon-76x76@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "76x76",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-76x76@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad",
|
||||
"size": "83.5x83.5",
|
||||
"scale": "2x",
|
||||
"filename": "App-Icon-83.5x83.5@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom": "ios-marketing",
|
||||
"size": "1024x1024",
|
||||
"scale": "1x",
|
||||
"filename": "ItunesArtwork@2x.png"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "expo"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 733 KiB |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "expo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal",
|
||||
"filename": "image.png",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"idiom": "universal",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"idiom": "universal",
|
||||
"scale": "3x"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "expo"
|
||||
}
|
||||
}
|
||||