diff --git a/android/app/build.gradle b/android/app/build.gradle index 947ce178..6411e770 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: "com.android.application" +apply plugin: 'com.google.gms.google-services' import com.android.build.OutputFile import org.apache.tools.ant.taskdefs.condition.Os diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 00000000..9d9e3d20 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,55 @@ +{ + "project_info": { + "project_number": "661638997772", + "project_id": "xmflsct-mastodon-app", + "storage_bucket": "xmflsct-mastodon-app.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:661638997772:android:4fd02851f757f8fa9f8b29", + "android_client_info": { + "package_name": "com.xmflsct.app.tooot" + } + }, + "oauth_client": [ + { + "client_id": "661638997772-erabggnp958v10r0tvsrh3pg880qnvqn.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.xmflsct.app.tooot", + "certificate_hash": "53162f104230ee8b7b1372e4f378e2b9607ca16f" + } + }, + { + "client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDUw4s-mhQsHvs4hdIsldsi68ZIygM5MC4" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "661638997772-6aiqk97aema0rt280i7nfar3ha2mlgno.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "661638997772-65g8ce369ugck3ii4ulk6jhb3ijg51kl.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.xmflsct.app.tooot", + "app_store_id": "1549772269" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 545f156f..3b22e22f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ + diff --git a/android/build.gradle b/android/build.gradle index 23aa8859..65e07931 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,6 +25,7 @@ buildscript { classpath('com.android.tools.build:gradle:7.2.2') classpath("com.facebook.react:react-native-gradle-plugin") classpath("de.undercouch:gradle-download-task:5.0.1") + classpath 'com.google.gms:google-services:4.3.14' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/app.config.ts b/app.config.ts index 0afae03f..087f6bc6 100644 --- a/app.config.ts +++ b/app.config.ts @@ -15,8 +15,9 @@ export default (): ExpoConfig => ({ }, android: { package: 'com.xmflsct.app.tooot', - permissions: ['CAMERA', 'VIBRATE'], - blockedPermissions: ['USE_BIOMETRIC', 'USE_FINGERPRINT'] + permissions: ['NOTIFICATIONS', 'CAMERA', 'VIBRATE'], + blockedPermissions: ['USE_BIOMETRIC', 'USE_FINGERPRINT'], + googleServicesFile: './android/app/google-services.json' }, plugins: [ [ diff --git a/package.json b/package.json index 144490ed..077a8776 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@react-native-community/blur": "^4.3.0", "@react-native-community/netinfo": "9.3.7", "@react-native-community/segmented-control": "^2.2.2", + "@react-native-firebase/app": "^16.5.0", "@react-native-menu/menu": "^0.7.3", "@react-navigation/bottom-tabs": "^6.5.2", "@react-navigation/native": "^6.1.1", diff --git a/src/screens/Tabs/Me/Push.tsx b/src/screens/Tabs/Me/Push.tsx index be76f88d..a62f1c06 100644 --- a/src/screens/Tabs/Me/Push.tsx +++ b/src/screens/Tabs/Me/Push.tsx @@ -33,36 +33,39 @@ const TabMePush: React.FC = () => { const [accountDomain] = useAccountStorage.string('auth.account.domain') const [accountId] = useAccountStorage.string('auth.account.id') - const appsQuery = useAppsQuery() + const appsQuery = useAppsQuery({ + options: { + onSuccess: async data => { + if (data.vapid_key) { + await checkPush() + if (isDevelopment) { + setPushAvailable(true) + } else { + setPushAvailable(!!expoToken?.length) + } + } + } + } + }) + + const checkPush = async () => { + const permissions = await Notifications.getPermissionsAsync() + setPushEnabled(permissions.granted) + setPushCanAskAgain(permissions.canAskAgain) + layoutAnimation() + await updateExpoToken() + } const [pushAvailable, setPushAvailable] = useState() const [pushEnabled, setPushEnabled] = useState() const [pushCanAskAgain, setPushCanAskAgain] = useState() useEffect(() => { - const checkPush = async () => { - const permissions = await Notifications.getPermissionsAsync() - setPushEnabled(permissions.granted) - setPushCanAskAgain(permissions.canAskAgain) - layoutAnimation() - await updateExpoToken() - } - - if (appsQuery.data?.vapid_key) { - checkPush() - - if (isDevelopment) { - setPushAvailable(true) - } else { - setPushAvailable(!!expoToken?.length) - } - } - const subscription = AppState.addEventListener('change', checkPush) return () => { subscription.remove() } - }, [appsQuery.data?.vapid_key]) + }, []) const alerts = () => push?.alerts @@ -222,11 +225,11 @@ const TabMePush: React.FC = () => { } }) + setAccountStorage([{ key: 'push', value: { ...push, global: true } }]) + if (Platform.OS === 'android') { setChannels(true) } - - setAccountStorage([{ key: 'push', value: { ...push, global: true } }]) } }} /> @@ -244,11 +247,11 @@ const TabMePush: React.FC = () => { body: { auth: push?.decode ? null : push.key } }) + setAccountStorage([{ key: 'push', value: { ...push, decode: !push.decode } }]) + if (Platform.OS === 'android') { setChannels(true) } - - setAccountStorage([{ key: 'push', value: { ...push, decode: !push.decode } }]) }} /> export const setChannels = async (reset: boolean | undefined = false, specificAccount?: string) => { const account = specificAccount || getGlobalStorage.string('account.active') - const accountDetails = getAccountDetails(['version', 'push']) + const accountDetails = getAccountDetails([ + 'version', + 'push', + 'auth.account.acct', + 'auth.account.domain' + ]) if (!account || !accountDetails) return null + const readableAccount = `@${accountDetails['auth.account.acct']}@${accountDetails['auth.account.domain']}` + const deleteChannel = async (type: string) => - Notifications.deleteNotificationChannelAsync(`${account}_${type}`) + Notifications.deleteNotificationChannelAsync(`${readableAccount}_${type}`) const setChannel = async (type: string) => - Notifications.setNotificationChannelAsync(`${account}_${type}`, { - groupId: account, + Notifications.setNotificationChannelAsync(`${readableAccount}_${type}`, { + groupId: readableAccount, name: i18n.t(`screenTabs:me.push.${type}.heading` as any), importance: Notifications.AndroidImportance.DEFAULT, bypassDnd: false, @@ -62,12 +69,12 @@ export const setChannels = async (reset: boolean | undefined = false, specificAc enableVibrate: true }) - const channelGroup = await Notifications.getNotificationChannelGroupAsync(account) + const channelGroup = await Notifications.getNotificationChannelGroupAsync(readableAccount) if (channelGroup && !reset) { return } if (!channelGroup) { - await Notifications.setNotificationChannelGroupAsync(account, { name: account }) + await Notifications.setNotificationChannelGroupAsync(readableAccount, { name: readableAccount }) } if (!accountDetails.push.decode) { diff --git a/yarn.lock b/yarn.lock index b43642b9..9e39eadf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1656,7 +1656,7 @@ __metadata: languageName: node linkType: hard -"@expo/config-plugins@npm:5.0.4, @expo/config-plugins@npm:~5.0.3": +"@expo/config-plugins@npm:5.0.4, @expo/config-plugins@npm:^5.0.4, @expo/config-plugins@npm:~5.0.3": version: 5.0.4 resolution: "@expo/config-plugins@npm:5.0.4" dependencies: @@ -2979,6 +2979,20 @@ __metadata: languageName: node linkType: hard +"@react-native-firebase/app@npm:^16.5.0": + version: 16.5.0 + resolution: "@react-native-firebase/app@npm:16.5.0" + dependencies: + "@expo/config-plugins": ^5.0.4 + opencollective-postinstall: ^2.0.1 + superstruct: ^0.6.2 + peerDependencies: + react: "*" + react-native: "*" + checksum: 2eab11544f8b4e932127119b6485e43788214df8264f1f84b06695ad1ca0ae88e9969c9e8d8005ab986637223991617960b1556dee43453cc38716d537d9c81a + languageName: node + linkType: hard + "@react-native-menu/menu@npm:^0.7.3": version: 0.7.3 resolution: "@react-native-menu/menu@npm:0.7.3" @@ -4619,6 +4633,18 @@ __metadata: languageName: node linkType: hard +"clone-deep@npm:^2.0.1": + version: 2.0.2 + resolution: "clone-deep@npm:2.0.2" + dependencies: + for-own: ^1.0.0 + is-plain-object: ^2.0.4 + kind-of: ^6.0.0 + shallow-clone: ^1.0.0 + checksum: c33ae31e332cdfd477a8115c9d044984eb69bf009fce3e1f0ff002176652f572d8742aa5e6caeaf16cf5d6084e33fe51bfa482fec53f43e767b3518c797955b1 + languageName: node + linkType: hard + "clone-deep@npm:^4.0.1": version: 4.0.1 resolution: "clone-deep@npm:4.0.1" @@ -6109,13 +6135,29 @@ __metadata: languageName: node linkType: hard -"for-in@npm:^1.0.2": +"for-in@npm:^0.1.3": + version: 0.1.8 + resolution: "for-in@npm:0.1.8" + checksum: f5bdad7811700ee6a0f96b33d72a1db966aea75a1f03c7245d147f8369305e709f53a55ee7ae8eaddcfa85c7c89bca78472be8f1bc605475ce5bb2c70f77f8da + languageName: node + linkType: hard + +"for-in@npm:^1.0.1, for-in@npm:^1.0.2": version: 1.0.2 resolution: "for-in@npm:1.0.2" checksum: 09f4ae93ce785d253ac963d94c7f3432d89398bf25ac7a24ed034ca393bf74380bdeccc40e0f2d721a895e54211b07c8fad7132e8157827f6f7f059b70b4043d languageName: node linkType: hard +"for-own@npm:^1.0.0": + version: 1.0.0 + resolution: "for-own@npm:1.0.0" + dependencies: + for-in: ^1.0.1 + checksum: 233238f6e9060f61295a7f7c7e3e9de11aaef57e82a108e7f350dc92ae84fe2189848077ac4b8db47fd8edd45337ed8d9f66bd0b1efa4a6a1b3f38aa21b7ab2e + languageName: node + linkType: hard + "form-data@npm:^3.0.1": version: 3.0.1 resolution: "form-data@npm:3.0.1" @@ -7557,7 +7599,7 @@ __metadata: languageName: node linkType: hard -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": +"kind-of@npm:^6.0.0, kind-of@npm:^6.0.1, kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b @@ -8418,6 +8460,16 @@ __metadata: languageName: node linkType: hard +"mixin-object@npm:^2.0.1": + version: 2.0.1 + resolution: "mixin-object@npm:2.0.1" + dependencies: + for-in: ^0.1.3 + is-extendable: ^0.1.1 + checksum: 7d0eb7c2f06435fcc01d132824b4c973a0df689a117d8199d79911b506363b6f4f86a84458a63f3acfa7388f3052612cfe27105400b4932678452925a9739a4c + languageName: node + linkType: hard + "mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.5, mkdirp@npm:~0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" @@ -8867,6 +8919,15 @@ __metadata: languageName: node linkType: hard +"opencollective-postinstall@npm:^2.0.1": + version: 2.0.3 + resolution: "opencollective-postinstall@npm:2.0.3" + bin: + opencollective-postinstall: index.js + checksum: 0a68c5cef135e46d11e665d5077398285d1ce5311c948e8327b435791c409744d4a6bb9c55bd6507fb5f2ef34b0ad920565adcdaf974cbdae701aead6f32b396 + languageName: node + linkType: hard + "opn@npm:^5.4.0": version: 5.5.0 resolution: "opn@npm:5.5.0" @@ -10496,6 +10557,17 @@ __metadata: languageName: node linkType: hard +"shallow-clone@npm:^1.0.0": + version: 1.0.0 + resolution: "shallow-clone@npm:1.0.0" + dependencies: + is-extendable: ^0.1.1 + kind-of: ^5.0.0 + mixin-object: ^2.0.1 + checksum: d4fd93b82d9fdd135027510f4beb04479de96c50b5392a17b022cf0942d17d43bff92aa83dfc30ddf962c0ed015e7c686c2ce677b85760ca5a8db9ebd5f1d791 + languageName: node + linkType: hard + "shallow-clone@npm:^3.0.0": version: 3.0.1 resolution: "shallow-clone@npm:3.0.1" @@ -11001,6 +11073,16 @@ __metadata: languageName: node linkType: hard +"superstruct@npm:^0.6.2": + version: 0.6.2 + resolution: "superstruct@npm:0.6.2" + dependencies: + clone-deep: ^2.0.1 + kind-of: ^6.0.1 + checksum: f95e4049becb928baa531fe56256a74b050a2e4da0bee09ccd0031e08fffd521defeb1d37881b93e6861fa1a7c17c48f3834a99af83cb3ad60c9e6079e840a65 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -11268,6 +11350,7 @@ __metadata: "@react-native-community/blur": ^4.3.0 "@react-native-community/netinfo": 9.3.7 "@react-native-community/segmented-control": ^2.2.2 + "@react-native-firebase/app": ^16.5.0 "@react-native-menu/menu": ^0.7.3 "@react-navigation/bottom-tabs": ^6.5.2 "@react-navigation/native": ^6.1.1