diff --git a/.envrc.example b/.envrc.example new file mode 100644 index 00000000..e5077692 --- /dev/null +++ b/.envrc.example @@ -0,0 +1,27 @@ +export TOOOT_ENVIRONMENT="" + +export SENTRY_ORGANIZATION="" +export SENTRY_PROJECT="" +export SENTRY_AUTH_TOKEN="" +export SENTRY_DSN="" + +# Fastlane start +export LC_ALL="" +export LANG="" + +export FASTLANE_USER="" + +export MATCH_PASSWORD="" +export MATCH_GIT_URL="" +export MATCH_GIT_BASIC_AUTHORIZATION="" + +export APP_STORE_CONNECT_API_KEY_KEY_ID="" +export APP_STORE_CONNECT_API_KEY_ISSUER_ID="" +export APP_STORE_CONNECT_API_KEY_KEY="" + +export ANDROID_KEYSTORE="" +export ANDROID_KEYSTORE_PASSWORD="" +export ANDROID_KEYSTORE_ALIAS="" +export ANDROID_KEYSTORE_KEY_PASSWORD="" +export SUPPLY_JSON_KEY_DATA="" +# Fastlane end \ No newline at end of file diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml new file mode 100644 index 00000000..01264fd6 --- /dev/null +++ b/.github/workflows/development.yml @@ -0,0 +1,50 @@ +name: Build development +on: + push: + branches: + - development +jobs: + build: + runs-on: macos-latest + steps: + - name: -- Step 1 -- Checkout code + uses: actions/checkout@v2 + - name: -- Step 2 -- Setup node + uses: actions/setup-node@v2 + with: + node-version: 14.x + - name: -- Step 3 -- Use Expo action + uses: expo/expo-github-action@v5 + with: + expo-version: 4.x + expo-username: ${{ secrets.EXPO_USERNAME }} + expo-token: ${{ secrets.EXPO_TOKEN }} + - name: -- Step 4 -- Install node dependencies + run: yarn install + - name: -- Step 5 -- Install native dependencies + run: npx pod-install + - name: -- Step 6 -- Install ruby dependencies + run: bundle install + - name: -- Step 7 -- Run fastlane + env: + TOOOT_ENVIRONMENT: development + SENTRY_ORGANIZATION: ${{ secrets.SENTRY_ORGANIZATION }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + LC_ALL: en_US.UTF-8 + LANG: en_US.UTF-8 + FASTLANE_USER: ${{ secrets.FASTLANE_USER }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} + MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} + APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }} + APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} + ANDROID_KEYSTORE: ${{ secrets.ANDROID_KEYSTORE }} + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEYSTORE_ALIAS }} + ANDROID_KEYSTORE_KEY_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_KEY_PASSWORD }} + SUPPLY_JSON_KEY_DATA: ${{ secrets.SUPPLY_JSON_KEY_DATA }} + FL_GITHUB_RELEASE_API_BEARER: ${{ secrets.GITHUB_TOKEN }} + run: yarn app:build diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 24a22ab1..01a69f64 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -15,7 +15,7 @@ case ENVIRONMENT when "development" GITHUB_RELEASE= "" when "staging" - GITHUB_RELEASE = "v#{VERSION}(#{BUILD_NUMBER})" + GITHUB_RELEASE = "v#{VERSION}-rc#{VERSIONS[:patch]}" when "production" GITHUB_RELEASE = "v#{VERSION}" end @@ -44,20 +44,14 @@ private_lane :prepare_playstore_android do end desc "Create new GitHub release" -private_lane :github_release do - case ENVIRONMENT - when "staging" - is_prerelease = true - when "production" - is_prerelease = false - end +private_lane :github_release do |options| set_github_release( repository_name: GITHUB_REPO, name: GITHUB_RELEASE, tag_name: GITHUB_RELEASE, description: "No changelog provided", commitish: git_branch, - is_prerelease: is_prerelease + is_prerelease: options[:prerelease] ) end @@ -76,8 +70,10 @@ private_lane :build_ios do case ENVIRONMENT when "development" match( type: "development", readonly: true ) - build_ios_app( export_method: "development", output_directory: BUILD_DIRECTORY, output_name: "#{VERSION}-#{BUILD_NUMBER}" ) - install_on_device( skip_wifi: true ) + if !is_ci + build_ios_app( export_method: "development", output_directory: BUILD_DIRECTORY ) + install_on_device( skip_wifi: true ) + end when "staging" prepare_appstore_ios match( type: "appstore", readonly: true ) @@ -101,14 +97,16 @@ private_lane :build_android do case ENVIRONMENT when "development" - build_android_app( - task: 'assemble', - build_type: 'debug', - project_dir: "./android" - ) - adb( - command: "install #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]}" - ) + if !is_ci + build_android_app( + task: 'assemble', + build_type: 'debug', + project_dir: "./android" + ) + adb( + command: "install #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]}" + ) + end when "staging" prepare_playstore_android build_android_app( @@ -127,7 +125,7 @@ private_lane :build_android do } ) upload_to_play_store( - track: "alpha", + track: "beta", skip_upload_metadata: true, skip_upload_changelogs: true, skip_upload_images: true, @@ -147,9 +145,9 @@ lane :build do build_android case ENVIRONMENT when "staging" - github_release + github_release(prerelease: true) when "production" - github_release + github_release(prerelease: false) end end expo_release diff --git a/package.json b/package.json index 0cfb7e35..901a178f 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "native": "210201", "major": 0, "minor": 3, - "patch": 0, + "patch": 1, "expo": "40.0.0" } } diff --git a/src/components/Instance.tsx b/src/components/Instance.tsx index 4dbf386a..b37347f0 100644 --- a/src/components/Instance.tsx +++ b/src/components/Instance.tsx @@ -1,11 +1,8 @@ import Button from '@components/Button' -import haptics from '@components/haptics' import Icon from '@components/Icon' -import { useNavigation } from '@react-navigation/native' import { useAppsQuery } from '@utils/queryHooks/apps' import { useInstanceQuery } from '@utils/queryHooks/instance' -import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import { getLocalInstances, remoteUpdate } from '@utils/slices/instancesSlice' +import { getLocalInstances } from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import * as WebBrowser from 'expo-web-browser' @@ -13,39 +10,30 @@ import { debounce } from 'lodash' import React, { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { Alert, Image, StyleSheet, Text, TextInput, View } from 'react-native' -import { useQueryClient } from 'react-query' -import { useDispatch, useSelector } from 'react-redux' +import { useSelector } from 'react-redux' import { Placeholder, Fade } from 'rn-placeholder' import analytics from './analytics' import InstanceAuth from './Instance/Auth' import EULA from './Instance/EULA' import InstanceInfo from './Instance/Info' -import { toast } from './toast' export interface Props { - type: 'local' | 'remote' disableHeaderImage?: boolean goBack?: boolean } const ComponentInstance: React.FC = ({ - type, disableHeaderImage, goBack = false }) => { - const { t, i18n } = useTranslation('componentInstance') + const { t } = useTranslation('componentInstance') const { theme } = useTheme() - const navigation = useNavigation() const localInstances = useSelector(getLocalInstances) - const dispatch = useDispatch() - - const queryClient = useQueryClient() const [instanceDomain, setInstanceDomain] = useState() const instanceQuery = useInstanceQuery({ instanceDomain, - checkPublic: type === 'remote', options: { enabled: false, retry: false } }) const appsQuery = useAppsQuery({ @@ -70,46 +58,30 @@ const ComponentInstance: React.FC = ({ const processUpdate = useCallback(() => { if (instanceDomain) { - switch (type) { - case 'local': - analytics('instance_local_login') - if ( - localInstances && - localInstances.filter(instance => instance.url === instanceDomain) - .length - ) { - Alert.alert( - t('update.local.alert.title'), - t('update.local.alert.message'), - [ - { - text: t('update.local.alert.buttons.cancel'), - style: 'cancel' - }, - { - text: t('update.local.alert.buttons.continue'), - onPress: () => { - appsQuery.refetch() - } - } - ] - ) - } else { - appsQuery.refetch() - } - break - case 'remote': - analytics('instance_remote_register') - haptics('Success') - const queryKey: QueryKeyTimeline = [ - 'Timeline', - { page: 'RemotePublic' } + analytics('instance_local_login') + if ( + localInstances && + localInstances.filter(instance => instance.url === instanceDomain) + .length + ) { + Alert.alert( + t('update.local.alert.title'), + t('update.local.alert.message'), + [ + { + text: t('update.local.alert.buttons.cancel'), + style: 'cancel' + }, + { + text: t('update.local.alert.buttons.continue'), + onPress: () => { + appsQuery.refetch() + } + } ] - dispatch(remoteUpdate(instanceDomain)) - queryClient.resetQueries(queryKey) - toast({ type: 'success', message: t('update.remote.succeed') }) - navigation.goBack() - break + ) + } else { + appsQuery.refetch() } } }, [instanceDomain]) @@ -129,15 +101,6 @@ const ComponentInstance: React.FC = ({ [instanceDomain, instanceQuery.isSuccess, instanceQuery.data] ) - const buttonContent = useMemo(() => { - switch (type) { - case 'local': - return t('server.button.local') - case 'remote': - return t('server.button.remote') - } - }, [i18n.language]) - const requestAuth = useMemo(() => { if ( instanceDomain && @@ -179,12 +142,9 @@ const ComponentInstance: React.FC = ({ styles.textInput, { color: theme.primary, - borderBottomColor: - type === 'remote' && - instanceQuery.data && - !instanceQuery.data.publicAllow - ? theme.red - : theme.border + borderBottomColor: instanceQuery.isError + ? theme.red + : theme.border } ]} onChangeText={onChangeText} @@ -200,13 +160,9 @@ const ComponentInstance: React.FC = ({ />