diff --git a/.envrc.example b/.envrc.example index ef1c1556..a45f2cc7 100644 --- a/.envrc.example +++ b/.envrc.example @@ -5,7 +5,7 @@ export SENTRY_PROJECT="" export SENTRY_AUTH_TOKEN="" export SENTRY_DSN="" -export TOOOT_API_KEY="" +export TOOOT_PUSH_KEY_PUBLIC="" # Fastlane start export LC_ALL="" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 94f53d66..89c58145 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} - TOOOT_API_KEY: ${{ secrets.TOOOT_API_KEY }} + TOOOT_PUSH_KEY_PUBLIC: ${{ secrets.TOOOT_PUSH_KEY_PUBLIC }} FASTLANE_USER: ${{ secrets.FASTLANE_USER }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} diff --git a/Gemfile.lock b/Gemfile.lock index 02b6ed5b..ffd2baba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.4) + CFPropertyList (3.0.5) rexml activesupport (6.1.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) @@ -17,17 +17,17 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.518.0) - aws-sdk-core (3.121.3) + aws-partitions (1.541.0) + aws-sdk-core (3.124.0) aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.239.0) + aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.50.0) - aws-sdk-core (~> 3, >= 3.121.2) + aws-sdk-kms (1.52.0) + aws-sdk-core (~> 3, >= 3.122.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.104.0) - aws-sdk-core (~> 3, >= 3.121.2) + aws-sdk-s3 (1.109.0) + aws-sdk-core (~> 3, >= 3.122.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) aws-sigv4 (1.4.0) @@ -86,7 +86,7 @@ GEM escape (0.0.4) ethon (0.15.0) ffi (>= 1.15.0) - excon (0.87.0) + excon (0.89.0) faraday (1.8.0) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -112,7 +112,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.5) - fastlane (2.197.0) + fastlane (2.199.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -152,14 +152,14 @@ GEM xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) fastlane-plugin-json (1.0.0) - fastlane-plugin-sentry (1.10.1) + fastlane-plugin-sentry (1.11.0) fastlane-plugin-versioning_android (0.1.0) fastlane-plugin-yarn (1.2) ffi (1.15.4) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.12.0) + google-apis-androidpublisher_v3 (0.14.0) google-apis-core (>= 0.4, < 2.a) google-apis-core (0.4.1) addressable (~> 2.5, >= 2.5.1) @@ -170,11 +170,11 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.7.0) + google-apis-iamcredentials_v1 (0.9.0) google-apis-core (>= 0.4, < 2.a) - google-apis-playcustomapp_v1 (0.5.0) + google-apis-playcustomapp_v1 (0.6.0) google-apis-core (>= 0.4, < 2.a) - google-apis-storage_v1 (0.8.0) + google-apis-storage_v1 (0.10.0) google-apis-core (>= 0.4, < 2.a) google-cloud-core (1.6.0) google-cloud-env (~> 1.0) @@ -182,15 +182,15 @@ GEM google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) google-cloud-errors (1.2.0) - google-cloud-storage (1.34.1) - addressable (~> 2.5) + google-cloud-storage (1.35.0) + addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) google-apis-storage_v1 (~> 0.1) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.0.0) + googleauth (1.1.0) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -218,7 +218,7 @@ GEM naturally (2.2.1) netrc (0.11.0) optparse (0.1.1) - os (1.1.1) + os (1.1.4) plist (3.6.0) public_suffix (4.0.6) rake (13.0.6) @@ -244,7 +244,7 @@ GEM terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - trailblazer-option (0.1.1) + trailblazer-option (0.1.2) tty-cursor (0.7.1) tty-screen (0.8.1) tty-spinner (0.9.3) @@ -275,6 +275,7 @@ GEM PLATFORMS universal-darwin-20 + universal-darwin-21 DEPENDENCIES cocoapods diff --git a/app.config.ts b/app.config.ts index 26c758be..7bf2ad1f 100644 --- a/app.config.ts +++ b/app.config.ts @@ -13,7 +13,7 @@ export default (): ExpoConfig => ({ assetBundlePatterns: ['assets/*'], extra: { sentryDSN: process.env.SENTRY_DSN, - toootApiKey: process.env.TOOOT_API_KEY + toootPushKeyPublic: process.env.TOOOT_PUSH_KEY_PUBLIC }, hooks: { postPublish: [ diff --git a/src/i18n/en/screens/tabs.json b/src/i18n/en/screens/tabs.json index ddb1cbfb..79d5b652 100644 --- a/src/i18n/en/screens/tabs.json +++ b/src/i18n/en/screens/tabs.json @@ -144,6 +144,7 @@ } }, "push": { + "notAvailable": "Your phone does not support tooot's push notification", "enable": { "direct": "Enable push notification", "settings": "Enable in settings" @@ -184,6 +185,12 @@ "empty": "None" } }, + "push": { + "content": { + "enabled": "Enabled", + "disabled": "Disabled" + } + }, "update": { "title": "Update to latest version" }, diff --git a/src/i18n/zh-Hans/screens/tabs.json b/src/i18n/zh-Hans/screens/tabs.json index 0671f3d4..e9dc4611 100644 --- a/src/i18n/zh-Hans/screens/tabs.json +++ b/src/i18n/zh-Hans/screens/tabs.json @@ -144,6 +144,7 @@ } }, "push": { + "notAvailable": "您的机型暂不支持 tooot 推送通知", "enable": { "direct": "启用推送通知", "settings": "在系统设置中启用" @@ -184,6 +185,12 @@ "empty": "无公告" } }, + "push": { + "content": { + "enabled": "已启用", + "disabled": "未启用" + } + }, "update": { "title": "更新至最新版本" }, diff --git a/src/screens/Announcements.tsx b/src/screens/Announcements.tsx index 734969dc..a00f0a72 100644 --- a/src/screens/Announcements.tsx +++ b/src/screens/Announcements.tsx @@ -20,9 +20,9 @@ import FastImage from 'react-native-fast-image' import { FlatList, ScrollView } from 'react-native-gesture-handler' import { SafeAreaView } from 'react-native-safe-area-context' -const ScreenAnnouncements: React.FC> = ({ +const ScreenAnnouncements: React.FC< + RootStackScreenProps<'Screen-Announcements'> +> = ({ route: { params: { showAll = false } }, @@ -250,6 +250,7 @@ const styles = StyleSheet.create({ announcementContainer: { width: Dimensions.get('screen').width, padding: StyleConstants.Spacing.Global.PagePadding, + marginVertical: StyleConstants.Spacing.Global.PagePadding, justifyContent: 'center' }, published: { diff --git a/src/screens/ImagesViewer.tsx b/src/screens/ImagesViewer.tsx index acffce27..0d6af38e 100644 --- a/src/screens/ImagesViewer.tsx +++ b/src/screens/ImagesViewer.tsx @@ -61,9 +61,11 @@ const HeaderComponent = React.memo( analytics('imageviewer_more_share_press') switch (Platform.OS) { case 'ios': - Share.share({ url: imageUrls[currentIndex].url }) + await Share.share({ url: imageUrls[currentIndex].url }) + break case 'android': - Share.share({ message: imageUrls[currentIndex].url }) + await Share.share({ message: imageUrls[currentIndex].url }) + break } break } diff --git a/src/screens/Tabs/Me/Push.tsx b/src/screens/Tabs/Me/Push.tsx index 75e6e26f..810c3366 100644 --- a/src/screens/Tabs/Me/Push.tsx +++ b/src/screens/Tabs/Me/Push.tsx @@ -1,5 +1,6 @@ import analytics from '@components/analytics' import Button from '@components/Button' +import Icon from '@components/Icon' import { MenuContainer, MenuRow } from '@components/Menu' import { updateInstancePush } from '@utils/slices/instances/updatePush' import { updateInstancePushAlert } from '@utils/slices/instances/updatePushAlert' @@ -12,14 +13,16 @@ import { } from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import layoutAnimation from '@utils/styles/layoutAnimation' +import { useTheme } from '@utils/styles/ThemeManager' import * as Notifications from 'expo-notifications' import * as WebBrowser from 'expo-web-browser' import React, { useState, useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { AppState, Linking, ScrollView } from 'react-native' +import { AppState, Linking, ScrollView, Text, View } from 'react-native' import { useDispatch, useSelector } from 'react-redux' const TabMePush: React.FC = () => { + const { theme } = useTheme() const { t } = useTranslation('screenTabs') const instanceAccount = useSelector( getInstanceAccount, @@ -30,6 +33,9 @@ const TabMePush: React.FC = () => { const dispatch = useDispatch() const instancePush = useSelector(getInstancePush) + const [pushAvailable, setPushAvailable] = useState( + undefined + ) const [pushEnabled, setPushEnabled] = useState() const [pushCanAskAgain, setPushCanAskAgain] = useState() const checkPush = async () => { @@ -39,10 +45,15 @@ const TabMePush: React.FC = () => { setPushCanAskAgain(settings.canAskAgain) } useEffect(() => { + Notifications.getExpoPushTokenAsync({ + experienceId: '@xmflsct/tooot' + }) + .then(data => setPushAvailable(!!data)) + .catch(() => setPushAvailable(false)) checkPush() - AppState.addEventListener('change', checkPush) + const subscription = AppState.addEventListener('change', checkPush) return () => { - AppState.removeEventListener('change', checkPush) + subscription.remove() } }, []) @@ -54,13 +65,15 @@ const TabMePush: React.FC = () => { const alerts = useMemo(() => { return instancePush?.alerts - ? (['follow', 'favourite', 'reblog', 'mention', 'poll'] as [ - 'follow', - 'favourite', - 'reblog', - 'mention', - 'poll' - ]).map(alert => ( + ? ( + ['follow', 'favourite', 'reblog', 'mention', 'poll'] as [ + 'follow', + 'favourite', + 'reblog', + 'mention', + 'poll' + ] + ).map(alert => ( { return ( - {pushEnabled === false ? ( - -