Skip to content

Commit

Permalink
Add Foreground notification system (#379)
Browse files Browse the repository at this point in the history
* Add Foreground notification system

* Close notification if canceled
  • Loading branch information
keyvan-m-sadeghi authored Feb 11, 2024
1 parent 03ecaab commit 9b6d508
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 308 deletions.
6 changes: 5 additions & 1 deletion apps/box/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>

<application
android:name=".MainApplication"
Expand Down Expand Up @@ -30,6 +32,8 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="fxblox" />
</intent-filter>
</activity>
</activity>
<service android:name="com.asterinet.react.bgactions.RNBackgroundActionsTask" android:exported="false" />
<service android:name="app.notifee.core.ForegroundService" android:foregroundServiceType="dataSync" />
</application>
</manifest>
1 change: 1 addition & 0 deletions apps/box/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@functionland/react-native-fula": "*",
"@gorhom/bottom-sheet": "*",
"@metamask/sdk-react": "*",
"@notifee/react-native": "*",
"@react-native-async-storage/async-storage": "*",
"@react-native-clipboard/clipboard": "*",
"@react-native-community/netinfo": "*",
Expand Down
2 changes: 1 addition & 1 deletion apps/box/src/navigation/navigationConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export type SettingsStackParamList = {
export type InitialSetupStackParamList = {
[Routes.Welcome]: undefined;
[Routes.LinkPassword]: undefined;
[Routes.ConnectToWallet]: { password: string };
[Routes.ConnectToWallet]: undefined;
[Routes.ConnectToBlox]: undefined;
[Routes.ConnectToExistingBlox]: undefined;
[Routes.ConnectToWifi]: undefined;
Expand Down
338 changes: 36 additions & 302 deletions apps/box/src/screens/InitialSetup/ConnectToWallet.screen.tsx
Original file line number Diff line number Diff line change
@@ -1,326 +1,60 @@
import '@walletconnect/react-native-compat';
import React, { useEffect, useState } from 'react';
import { ActivityIndicator } from 'react-native';
import React from 'react';
import {
FxBox,
FxButton,
FxPicker,
FxPickerItem,
FxProgressBar,
FxSafeAreaBox,
FxText,
useToast,
} from '@functionland/component-library';
import { useInitialSetupNavigation } from '../../hooks/useTypedNavigation';
import { Routes } from '../../navigation/navigationConfig';
import { useUserProfileStore } from '../../stores/useUserProfileStore';
import { Helper } from '../../utils';
import { WalletDetails } from '../../components/WalletDetails';
import { useSDK } from '@metamask/sdk-react';
import { useLogger } from '../../hooks';
import {
chains,
goerliChainId,
mumbaiChainId,
ethereumChainId,
} from '../../utils/walletConnectConifg';
import notifee from '@notifee/react-native';

export const ConnectToWalletScreen = () => {
const navigation = useInitialSetupNavigation();
const [networkConfirmed, setNetworkConfirmed] = useState<boolean>(false);
const [selectedChainId, setSelectedChainId] = useState<string>(mumbaiChainId); // Mumbai Polygon Testnet
const { queueToast } = useToast();
const { account, chainId, provider, sdk, connected, connecting } = useSDK();

const [walletId, signiture, password, setWalletId] = useUserProfileStore(
(state) => [
state.walletId,
state.signiture,
state.password,
state.setWalletId,
]
);

const switchChain = async (_chainId: string) => {
return await provider?.request({
method: 'wallet_switchEthereumChain',
params: [
{
chainId: _chainId,
const allowNotifications = async () => {
await notifee.requestPermission();
notifee.registerForegroundService(async () => {});
await notifee.createChannel({
id: 'sticky',
name: 'Sticky Channel'
})
await notifee.displayNotification({
id: 'wallet',
title: 'warmup',
body: 'warmup',
android: {
progress: {
indeterminate: true
},
],
});
};

const addChain = async (_chainId: string) => {
return await provider?.request({
method: 'wallet_addEthereumChain',
params: [
{
...chains[_chainId],
pressAction: {
id: 'default'
},
],
});
};

const logger = useLogger();
useEffect(() => {
console.log('provider', provider);
if (!provider || !account) return;
if (account !== walletId) {
setWalletId(account, true);
}
}, [provider, account]);

const handleConnect = async () => {
//Added a `setNetwork` here as we do not need to select chain here anymoe
try {
await sdk?.connect();
} catch (err) {
console.log(err);
logger.logError('handleConnect', err);
queueToast({
title: 'Metamask linking error',
message: err.toString(),
type: 'error',
autoHideDuration: 3000,
});
disconnectWallet();
}
};

useEffect(() => {
/*if (connected && chainId !== undefined && chainId !== selectedChainId && networkConfirmed) {
setNetworkConfirmed(false);
let err = 'chainId does not match the selected chain';
console.log(err);
logger.logError('chianId check', err);
queueToast({
title: 'Metamask chain error',
message: err,
type: 'error',
autoHideDuration: 3000,
});
return;
}*/
if (connected && chainId) {
setNetworkConfirmed(true);
}
}, [chainId, connected]);

const handleNetwork = async () => {
if (chainId !== selectedChainId) {
try {
await addChain(selectedChainId);
} catch (e) {
console.log(
'###################### chain could not be added. trying switch: ',
e
);
try {
await switchChain(selectedChainId);
// eslint-disable-next-line no-catch-shadow
} catch (e) {
console.log(e);
logger.logError('handleNetwork, add chain', e);
queueToast({
title: 'Error adding chain to MetaMask',
message: JSON.stringify(e.toString()),
type: 'error',
autoHideDuration: 3000,
});
disconnectWallet();
return;
}
ongoing: true,
asForegroundService: true,
channelId: 'sticky'
}
}
setNetworkConfirmed(true);
};

const disconnectWallet = () => {
setNetworkConfirmed(false);
sdk?.terminate();
};
const handleLinkPassword = () => {
provider
?.request({
method: 'wallet_requestPermissions ',
params: [],
})
.then((res) => {
console.log('handlelink wallet request');
console.log(res);
navigation.navigate(Routes.LinkPassword);
})
.catch((e) => {
console.log(e);
navigation.navigate(Routes.LinkPassword);
});
};
})
notifee.stopForegroundService();
navigation.navigate(Routes.LinkPassword);
}

const handleConnectToBlox = () => {
navigation.navigate(Routes.ConnectToBlox);
};
const handleConnectToExistingBlox = () => {
navigation.navigate(Routes.ConnectToExistingBlox);
};

const handleOnBluetoothCommand = () => {
navigation.navigate(Routes.BluetoothCommands);
};
const handleSkipToManulaSetup = () => {
navigation.navigate(Routes.SetBloxAuthorizer, { isManualSetup: true });
};
return (
<FxSafeAreaBox flex={1} paddingHorizontal="20" paddingVertical="16">
<FxProgressBar progress={20} />

<FxBox flex={1} justifyContent="space-between" paddingVertical="80">
{provider && chainId && networkConfirmed ? (
<>
<WalletDetails allowChangeWallet={true} />
{password && signiture ? (
<FxBox>
<FxText variant="h300" textAlign="center">
Your DID
</FxText>
<FxText textAlign="center" marginTop="8">
{Helper.getMyDID(password, signiture)}
</FxText>
</FxBox>
) : null}
</>
) : (
<>
<FxText variant="h300" textAlign="center">
Connect To Wallet
</FxText>
{chainId && !networkConfirmed && (
<FxBox>
<FxText variant="h200" marginBottom="8">
Select network
</FxText>
<FxPicker
selectedValue={selectedChainId}
enabled={connected && !networkConfirmed}
onValueChange={(itemValue: string) =>
setSelectedChainId(itemValue)
}
>
<FxPickerItem
key={1}
label="Ethereum Mainnet"
value={'0x1'}
enabled={true}
/>
<FxPickerItem
key={5}
label="Goerli Ethereum Testnet"
value={goerliChainId}
/>
<FxPickerItem
key={137}
label="Polygon Mainnet"
value={'0x89'}
enabled={false}
/>
<FxPickerItem
key={80001}
label="Mumbai Polygon Testnet (Preferred)"
value={mumbaiChainId}
/>
</FxPicker>
</FxBox>
)}
</>
)}
<FxBox>
{!networkConfirmed ? (
<FxButton
size="large"
onPress={
provider
? chainId
? handleNetwork
: connecting
? disconnectWallet
: handleConnect
: () => {
queueToast({
title: 'Provider is not ready',
message: 'Provider is being prepared',
type: 'error',
autoHideDuration: 3000,
});
}
}
>
{provider ? (
chainId ? (
'Confirm'
) : connecting ? (
'Disconnect'
) : (
'Connect to Wallet'
)
) : (
<ActivityIndicator />
)}
</FxButton>
) : !signiture && chainId ? (
<FxButton
size="large"
onPress={provider ? handleLinkPassword : () => {}}
>
{provider ? 'Next' : <ActivityIndicator />}
</FxButton>
) : (
<>
<FxButton
size="large"
marginVertical="16"
onPress={handleConnectToBlox}
>
Connect to new Blox
</FxButton>
<FxButton
size="large"
variant="inverted"
onPress={handleConnectToExistingBlox}
>
Reconnect to existing Blox
</FxButton>
{logger.isDebugModeEnable && (
<FxButton
size="large"
variant="inverted"
marginTop="16"
onPress={handleOnBluetoothCommand}
>
Bluetooth commands
</FxButton>
)}
<FxButton
variant="inverted"
marginTop="16"
onPress={handleSkipToManulaSetup}
>
Skip to manual setup
</FxButton>
</>
)}
{provider && connected && (
<FxButton
variant="inverted"
size="large"
marginTop="8"
onPress={disconnectWallet}
>
Disconnect wallet
</FxButton>
)}
<FxBox flex={1} justifyContent="space-between" paddingVertical="80">
<FxText variant="h300" textAlign="center">
Connect To Wallet
</FxText>
<FxText>App needs notification permission to connect your wallet and perform data sync. Tap allow in the next prompt.</FxText>
<FxButton
size="large"
onPress={allowNotifications}
>
Allow Notifications
</FxButton>
</FxBox>
</FxBox>
</FxSafeAreaBox>
);
};
Loading

0 comments on commit 9b6d508

Please sign in to comment.