mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-12 10:30:36 +01:00
Merge pull request #7140 from BlueWallet/notio
FIX: When user uses custom electrum server, make him aware that his a…
This commit is contained in:
commit
dacd26531c
5 changed files with 235 additions and 198 deletions
|
@ -147,7 +147,7 @@ function Notifications(props) {
|
||||||
ActionSheet.showActionSheetWithOptions(
|
ActionSheet.showActionSheetWithOptions(
|
||||||
{
|
{
|
||||||
title: loc.settings.notifications,
|
title: loc.settings.notifications,
|
||||||
message: loc.notifications.would_you_like_to_receive_notifications,
|
message: `${loc.notifications.would_you_like_to_receive_notifications}\n${loc.settings.push_notifications_explanation}`,
|
||||||
options,
|
options,
|
||||||
cancelButtonIndex: 0, // Assuming 'no and don't ask' is still treated as the cancel action
|
cancelButtonIndex: 0, // Assuming 'no and don't ask' is still treated as the cancel action
|
||||||
anchor: anchor ? findNodeHandle(anchor.current) : undefined,
|
anchor: anchor ? findNodeHandle(anchor.current) : undefined,
|
||||||
|
|
|
@ -302,8 +302,8 @@
|
||||||
"privacy_clipboard_explanation": "Provide shortcuts if an address or invoice is found in your clipboard.",
|
"privacy_clipboard_explanation": "Provide shortcuts if an address or invoice is found in your clipboard.",
|
||||||
"privacy_do_not_track": "Disable Analytics",
|
"privacy_do_not_track": "Disable Analytics",
|
||||||
"privacy_do_not_track_explanation": "Performance and reliability information will not be submitted for analysis.",
|
"privacy_do_not_track_explanation": "Performance and reliability information will not be submitted for analysis.",
|
||||||
"push_notifications": "Push Notifications",
|
|
||||||
"rate": "Rate",
|
"rate": "Rate",
|
||||||
|
"push_notifications_explanation": "By enabling notifications, your device token will be sent to the server, along with wallet addresses and transaction IDs for all wallets and transactions made after enabling notifications. The device token is used to send notifications, and the wallet information allows us to notify you about incoming Bitcoin or transaction confirmations.\n\nOnly information from after you enable notifications is transmitted—nothing from before is collected.\n\nDisabling notifications will remove all of this information from the server. Additionally, deleting a wallet from the app will also remove its associated information from the server.",
|
||||||
"selfTest": "Self-Test",
|
"selfTest": "Self-Test",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"saved": "Saved",
|
"saved": "Saved",
|
||||||
|
@ -315,6 +315,7 @@
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"would_you_like_to_receive_notifications": "Would you like to receive notifications when you get incoming payments?",
|
"would_you_like_to_receive_notifications": "Would you like to receive notifications when you get incoming payments?",
|
||||||
|
"notifications_subtitle": "Incoming payments and transaction confirmations",
|
||||||
"no_and_dont_ask": "No, and do not ask me again.",
|
"no_and_dont_ask": "No, and do not ask me again.",
|
||||||
"ask_me_later": "Ask me later."
|
"ask_me_later": "Ask me later."
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ const DefaultView = lazy(() => import('../screen/settings/DefaultView'));
|
||||||
const ElectrumSettings = lazy(() => import('../screen/settings/electrumSettings'));
|
const ElectrumSettings = lazy(() => import('../screen/settings/electrumSettings'));
|
||||||
const EncryptStorage = lazy(() => import('../screen/settings/EncryptStorage'));
|
const EncryptStorage = lazy(() => import('../screen/settings/EncryptStorage'));
|
||||||
const LightningSettings = lazy(() => import('../screen/settings/LightningSettings'));
|
const LightningSettings = lazy(() => import('../screen/settings/LightningSettings'));
|
||||||
const NotificationSettings = lazy(() => import('../screen/settings/notificationSettings'));
|
const NotificationSettings = lazy(() => import('../screen/settings/NotificationSettings'));
|
||||||
const SelfTest = lazy(() => import('../screen/settings/SelfTest'));
|
const SelfTest = lazy(() => import('../screen/settings/SelfTest'));
|
||||||
const ReleaseNotes = lazy(() => import('../screen/settings/ReleaseNotes'));
|
const ReleaseNotes = lazy(() => import('../screen/settings/ReleaseNotes'));
|
||||||
const Tools = lazy(() => import('../screen/settings/tools'));
|
const Tools = lazy(() => import('../screen/settings/tools'));
|
||||||
|
|
231
screen/settings/NotificationSettings.tsx
Normal file
231
screen/settings/NotificationSettings.tsx
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { I18nManager, Linking, ScrollView, StyleSheet, TextInput, View, Pressable } from 'react-native';
|
||||||
|
import { Button as ButtonRNElements } from '@rneui/themed';
|
||||||
|
// @ts-ignore: no declaration file
|
||||||
|
import Notifications from '../../blue_modules/notifications';
|
||||||
|
import { BlueCard, BlueSpacing20, BlueText } from '../../BlueComponents';
|
||||||
|
import presentAlert from '../../components/Alert';
|
||||||
|
import { Button } from '../../components/Button';
|
||||||
|
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
|
||||||
|
import ListItem, { PressableWrapper } from '../../components/ListItem';
|
||||||
|
import { useTheme } from '../../components/themes';
|
||||||
|
import loc from '../../loc';
|
||||||
|
import { Divider } from '@rneui/base';
|
||||||
|
|
||||||
|
const NotificationSettings: React.FC = () => {
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [isNotificationsEnabled, setNotificationsEnabled] = useState(false);
|
||||||
|
const [tokenInfo, setTokenInfo] = useState('<empty>');
|
||||||
|
const [URI, setURI] = useState<string | undefined>();
|
||||||
|
const [tapCount, setTapCount] = useState(0);
|
||||||
|
const { colors } = useTheme();
|
||||||
|
const stylesWithThemeHook = {
|
||||||
|
root: {
|
||||||
|
backgroundColor: colors.background,
|
||||||
|
},
|
||||||
|
scroll: {
|
||||||
|
backgroundColor: colors.background,
|
||||||
|
},
|
||||||
|
scrollBody: {
|
||||||
|
backgroundColor: colors.background,
|
||||||
|
},
|
||||||
|
uri: {
|
||||||
|
borderColor: colors.formBorder,
|
||||||
|
borderBottomColor: colors.formBorder,
|
||||||
|
backgroundColor: colors.inputBackgroundColor,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTap = () => {
|
||||||
|
setTapCount(prevCount => prevCount + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onNotificationsSwitch = async (value: boolean) => {
|
||||||
|
try {
|
||||||
|
setNotificationsEnabled(value);
|
||||||
|
if (value) {
|
||||||
|
// User is enabling notifications
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.cleanUserOptOutFlag();
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
if (await Notifications.getPushToken()) {
|
||||||
|
// we already have a token, so we just need to reenable ALL level on groundcontrol:
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.setLevels(true);
|
||||||
|
} else {
|
||||||
|
// ok, we dont have a token. we need to try to obtain permissions, configure callbacks and save token locally:
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.tryToObtainPermissions();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User is disabling notifications
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.setLevels(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
setNotificationsEnabled(await Notifications.isNotificationsEnabled());
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
presentAlert({ message: (error as Error).message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
setNotificationsEnabled(await Notifications.isNotificationsEnabled());
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
setURI(await Notifications.getSavedUri());
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
setTokenInfo(
|
||||||
|
'token: ' +
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
JSON.stringify(await Notifications.getPushToken()) +
|
||||||
|
' permissions: ' +
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
JSON.stringify(await Notifications.checkPermissions()) +
|
||||||
|
' stored notifications: ' +
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
JSON.stringify(await Notifications.getStoredNotifications()),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
presentAlert({ message: (e as Error).message });
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const save = useCallback(async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
if (URI) {
|
||||||
|
// validating only if its not empty. empty means use default
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
if (await Notifications.isGroundControlUriValid(URI)) {
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.saveUri(URI);
|
||||||
|
presentAlert({ message: loc.settings.saved });
|
||||||
|
} else {
|
||||||
|
presentAlert({ message: loc.settings.not_a_valid_uri });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
await Notifications.saveUri('');
|
||||||
|
presentAlert({ message: loc.settings.saved });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(error);
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
}, [URI]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScrollView style={stylesWithThemeHook.scroll} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
||||||
|
<ListItem
|
||||||
|
Component={PressableWrapper}
|
||||||
|
title={loc.settings.notifications}
|
||||||
|
subtitle={loc.notifications.notifications_subtitle}
|
||||||
|
disabled={isLoading}
|
||||||
|
switch={{ onValueChange: onNotificationsSwitch, value: isNotificationsEnabled, testID: 'NotificationsSwitch' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pressable onPress={handleTap}>
|
||||||
|
<BlueCard>
|
||||||
|
<BlueText style={styles.multilineText}>{loc.settings.push_notifications_explanation}</BlueText>
|
||||||
|
</BlueCard>
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
{tapCount >= 10 && (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<BlueCard>
|
||||||
|
<BlueText>{loc.settings.groundcontrol_explanation}</BlueText>
|
||||||
|
</BlueCard>
|
||||||
|
|
||||||
|
<ButtonRNElements
|
||||||
|
icon={{
|
||||||
|
name: 'github',
|
||||||
|
type: 'font-awesome',
|
||||||
|
color: colors.foregroundColor,
|
||||||
|
}}
|
||||||
|
onPress={() => Linking.openURL('https://github.com/BlueWallet/GroundControl')}
|
||||||
|
titleStyle={{ color: colors.buttonAlternativeTextColor }}
|
||||||
|
title="github.com/BlueWallet/GroundControl"
|
||||||
|
color={colors.buttonTextColor}
|
||||||
|
buttonStyle={styles.buttonStyle}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BlueCard>
|
||||||
|
<View style={[styles.uri, stylesWithThemeHook.uri]}>
|
||||||
|
<TextInput
|
||||||
|
// @ts-ignore: refactor later
|
||||||
|
placeholder={Notifications.getDefaultUri()}
|
||||||
|
value={URI}
|
||||||
|
onChangeText={setURI}
|
||||||
|
numberOfLines={1}
|
||||||
|
style={styles.uriText}
|
||||||
|
placeholderTextColor="#81868e"
|
||||||
|
editable={!isLoading}
|
||||||
|
textContentType="URL"
|
||||||
|
autoCapitalize="none"
|
||||||
|
underlineColorAndroid="transparent"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<BlueSpacing20 />
|
||||||
|
<BlueText style={styles.centered} onPress={() => setTapCount(tapCount + 1)}>
|
||||||
|
♪ Ground Control to Major Tom ♪
|
||||||
|
</BlueText>
|
||||||
|
<BlueText style={styles.centered} onPress={() => setTapCount(tapCount + 1)}>
|
||||||
|
♪ Commencing countdown, engines on ♪
|
||||||
|
</BlueText>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<CopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<BlueSpacing20 />
|
||||||
|
<Button onPress={save} title={loc.settings.save} />
|
||||||
|
</BlueCard>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
uri: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderBottomWidth: 0.5,
|
||||||
|
minHeight: 44,
|
||||||
|
height: 44,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
centered: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
uriText: {
|
||||||
|
flex: 1,
|
||||||
|
color: '#81868e',
|
||||||
|
marginHorizontal: 8,
|
||||||
|
minHeight: 36,
|
||||||
|
height: 36,
|
||||||
|
},
|
||||||
|
buttonStyle: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row',
|
||||||
|
},
|
||||||
|
multilineText: {
|
||||||
|
textAlign: 'left',
|
||||||
|
lineHeight: 20,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default NotificationSettings;
|
|
@ -1,195 +0,0 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
|
||||||
import { I18nManager, Linking, ScrollView, StyleSheet, TextInput, TouchableWithoutFeedback, View } from 'react-native';
|
|
||||||
import { Button as ButtonRNElements } from '@rneui/themed';
|
|
||||||
|
|
||||||
import Notifications from '../../blue_modules/notifications';
|
|
||||||
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
|
|
||||||
import presentAlert from '../../components/Alert';
|
|
||||||
import { Button } from '../../components/Button';
|
|
||||||
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
|
|
||||||
import ListItem from '../../components/ListItem';
|
|
||||||
import { BlueCurrentTheme, useTheme } from '../../components/themes';
|
|
||||||
import loc from '../../loc';
|
|
||||||
|
|
||||||
const NotificationSettings = () => {
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [isNotificationsEnabled, setNotificationsEnabled] = useState(false);
|
|
||||||
const [isShowTokenInfo, setShowTokenInfo] = useState(0);
|
|
||||||
const [tokenInfo, setTokenInfo] = useState('<empty>');
|
|
||||||
const [URI, setURI] = useState();
|
|
||||||
|
|
||||||
const { colors } = useTheme();
|
|
||||||
|
|
||||||
const onNotificationsSwitch = async value => {
|
|
||||||
setNotificationsEnabled(value); // so the slider is not 'jumpy'
|
|
||||||
if (value) {
|
|
||||||
// user is ENABLING notifications
|
|
||||||
await Notifications.cleanUserOptOutFlag();
|
|
||||||
if (await Notifications.getPushToken()) {
|
|
||||||
// we already have a token, so we just need to reenable ALL level on groundcontrol:
|
|
||||||
await Notifications.setLevels(true);
|
|
||||||
} else {
|
|
||||||
// ok, we dont have a token. we need to try to obtain permissions, configure callbacks and save token locally:
|
|
||||||
await Notifications.tryToObtainPermissions();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// user is DISABLING notifications
|
|
||||||
await Notifications.setLevels(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setNotificationsEnabled(await Notifications.isNotificationsEnabled());
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
setNotificationsEnabled(await Notifications.isNotificationsEnabled());
|
|
||||||
setURI(await Notifications.getSavedUri());
|
|
||||||
setTokenInfo(
|
|
||||||
'token: ' +
|
|
||||||
JSON.stringify(await Notifications.getPushToken()) +
|
|
||||||
' permissions: ' +
|
|
||||||
JSON.stringify(await Notifications.checkPermissions()) +
|
|
||||||
' stored notifications: ' +
|
|
||||||
JSON.stringify(await Notifications.getStoredNotifications()),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
console.debug(e);
|
|
||||||
presentAlert({ message: e.message });
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const stylesWithThemeHook = {
|
|
||||||
root: {
|
|
||||||
...styles.root,
|
|
||||||
backgroundColor: colors.background,
|
|
||||||
},
|
|
||||||
scroll: {
|
|
||||||
...styles.scroll,
|
|
||||||
backgroundColor: colors.background,
|
|
||||||
},
|
|
||||||
scrollBody: {
|
|
||||||
...styles.scrollBody,
|
|
||||||
backgroundColor: colors.background,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const save = useCallback(async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
|
||||||
if (URI) {
|
|
||||||
// validating only if its not empty. empty means use default
|
|
||||||
if (await Notifications.isGroundControlUriValid(URI)) {
|
|
||||||
await Notifications.saveUri(URI);
|
|
||||||
presentAlert({ message: loc.settings.saved });
|
|
||||||
} else {
|
|
||||||
presentAlert({ message: loc.settings.not_a_valid_uri });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await Notifications.saveUri('');
|
|
||||||
presentAlert({ message: loc.settings.saved });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
}, [URI]);
|
|
||||||
|
|
||||||
return isLoading ? (
|
|
||||||
<BlueLoading />
|
|
||||||
) : (
|
|
||||||
<ScrollView style={stylesWithThemeHook.scroll} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
|
||||||
<ListItem
|
|
||||||
Component={TouchableWithoutFeedback}
|
|
||||||
title={loc.settings.push_notifications}
|
|
||||||
subtitle={loc.settings.groundcontrol_explanation}
|
|
||||||
switch={{ onValueChange: onNotificationsSwitch, value: isNotificationsEnabled, testID: 'NotificationsSwitch' }}
|
|
||||||
/>
|
|
||||||
<BlueSpacing20 />
|
|
||||||
|
|
||||||
<ButtonRNElements
|
|
||||||
icon={{
|
|
||||||
name: 'github',
|
|
||||||
type: 'font-awesome',
|
|
||||||
color: colors.foregroundColor,
|
|
||||||
}}
|
|
||||||
onPress={() => Linking.openURL('https://github.com/BlueWallet/GroundControl')}
|
|
||||||
titleStyle={{ color: colors.buttonAlternativeTextColor }}
|
|
||||||
title="github.com/BlueWallet/GroundControl"
|
|
||||||
color={colors.buttonTextColor}
|
|
||||||
buttonStyle={styles.buttonStyle}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<BlueCard>
|
|
||||||
<View style={styles.uri}>
|
|
||||||
<TextInput
|
|
||||||
placeholder={Notifications.getDefaultUri()}
|
|
||||||
value={URI}
|
|
||||||
onChangeText={setURI}
|
|
||||||
numberOfLines={1}
|
|
||||||
style={styles.uriText}
|
|
||||||
placeholderTextColor="#81868e"
|
|
||||||
editable={!isLoading}
|
|
||||||
textContentType="URL"
|
|
||||||
autoCapitalize="none"
|
|
||||||
underlineColorAndroid="transparent"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<BlueSpacing20 />
|
|
||||||
<BlueText style={styles.centered} onPress={() => setShowTokenInfo(isShowTokenInfo + 1)}>
|
|
||||||
♪ Ground Control to Major Tom ♪
|
|
||||||
</BlueText>
|
|
||||||
<BlueText style={styles.centered} onPress={() => setShowTokenInfo(isShowTokenInfo + 1)}>
|
|
||||||
♪ Commencing countdown, engines on ♪
|
|
||||||
</BlueText>
|
|
||||||
|
|
||||||
{isShowTokenInfo >= 9 && (
|
|
||||||
<View>
|
|
||||||
<CopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<BlueSpacing20 />
|
|
||||||
<Button onPress={save} title={loc.settings.save} />
|
|
||||||
</BlueCard>
|
|
||||||
</ScrollView>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
root: {
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
uri: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
borderColor: BlueCurrentTheme.colors.formBorder,
|
|
||||||
borderBottomColor: BlueCurrentTheme.colors.formBorder,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderBottomWidth: 0.5,
|
|
||||||
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
|
||||||
minHeight: 44,
|
|
||||||
height: 44,
|
|
||||||
alignItems: 'center',
|
|
||||||
borderRadius: 4,
|
|
||||||
},
|
|
||||||
centered: {
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
uriText: {
|
|
||||||
flex: 1,
|
|
||||||
color: '#81868e',
|
|
||||||
marginHorizontal: 8,
|
|
||||||
minHeight: 36,
|
|
||||||
height: 36,
|
|
||||||
},
|
|
||||||
buttonStyle: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default NotificationSettings;
|
|
Loading…
Add table
Reference in a new issue