mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-24 15:36:59 +01:00
Merge pull request #6248 from BlueWallet/multisig
FIX: Multisig Forget alerts where visible after closing modal (macOS)
This commit is contained in:
commit
fc221e9c56
7 changed files with 116 additions and 55 deletions
|
@ -1,9 +1,11 @@
|
||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
|
|
||||||
import { View, StyleSheet, Text, TouchableOpacity, ActivityIndicator } from 'react-native';
|
import { View, StyleSheet, Text, TouchableOpacity, ActivityIndicator, findNodeHandle } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useTheme } from './themes';
|
import { useTheme } from './themes';
|
||||||
|
import ActionSheetOptions from '../screen/ActionSheet.common';
|
||||||
|
import ActionSheet from '../screen/ActionSheet';
|
||||||
export const MultipleStepsListItemDashType = Object.freeze({ none: 0, top: 1, bottom: 2, topAndBottom: 3 });
|
export const MultipleStepsListItemDashType = Object.freeze({ none: 0, top: 1, bottom: 2, topAndBottom: 3 });
|
||||||
export const MultipleStepsListItemButtohType = Object.freeze({ partial: 0, full: 1 });
|
export const MultipleStepsListItemButtohType = Object.freeze({ partial: 0, full: 1 });
|
||||||
|
|
||||||
|
@ -15,6 +17,8 @@ const MultipleStepsListItem = props => {
|
||||||
circledText = '',
|
circledText = '',
|
||||||
leftText = '',
|
leftText = '',
|
||||||
checked = false,
|
checked = false,
|
||||||
|
useActionSheet = false,
|
||||||
|
actionSheetOptions = null, // Default to null or appropriate default
|
||||||
} = props;
|
} = props;
|
||||||
const stylesHook = StyleSheet.create({
|
const stylesHook = StyleSheet.create({
|
||||||
provideKeyButton: {
|
provideKeyButton: {
|
||||||
|
@ -36,6 +40,29 @@ const MultipleStepsListItem = props => {
|
||||||
color: colors.alternativeTextColor,
|
color: colors.alternativeTextColor,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const selfRef = useRef(null); // Create a ref for the component itself
|
||||||
|
|
||||||
|
const handleOnPressForActionSheet = () => {
|
||||||
|
if (useActionSheet && actionSheetOptions) {
|
||||||
|
// Clone options to modify them
|
||||||
|
let modifiedOptions = { ...actionSheetOptions };
|
||||||
|
|
||||||
|
// Use 'selfRef' if the component uses its own ref, or 'ref' if it's using forwarded ref
|
||||||
|
const anchor = findNodeHandle(selfRef.current);
|
||||||
|
|
||||||
|
if (anchor) {
|
||||||
|
// Attach the anchor only if it exists
|
||||||
|
modifiedOptions = { ...modifiedOptions, anchor };
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionSheet.showActionSheetWithOptions(modifiedOptions, buttonIndex => {
|
||||||
|
// Call the original onPress function, if provided, and not cancelled
|
||||||
|
if (buttonIndex !== -1 && props.button.onPress) {
|
||||||
|
props.button.onPress(buttonIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const renderDashes = () => {
|
const renderDashes = () => {
|
||||||
switch (dashes) {
|
switch (dashes) {
|
||||||
|
@ -106,11 +133,12 @@ const MultipleStepsListItem = props => {
|
||||||
{props.button.buttonType === undefined ||
|
{props.button.buttonType === undefined ||
|
||||||
(props.button.buttonType === MultipleStepsListItemButtohType.full && (
|
(props.button.buttonType === MultipleStepsListItemButtohType.full && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
ref={useActionSheet ? selfRef : null}
|
||||||
testID={props.button.testID}
|
testID={props.button.testID}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
disabled={props.button.disabled}
|
disabled={props.button.disabled}
|
||||||
style={[styles.provideKeyButton, stylesHook.provideKeyButton, buttonOpacity]}
|
style={[styles.provideKeyButton, stylesHook.provideKeyButton, buttonOpacity]}
|
||||||
onPress={props.button.onPress}
|
onPress={useActionSheet ? handleOnPressForActionSheet : props.button.onPress}
|
||||||
>
|
>
|
||||||
<Text style={[styles.provideKeyButtonText, stylesHook.provideKeyButtonText]}>{props.button.text}</Text>
|
<Text style={[styles.provideKeyButtonText, stylesHook.provideKeyButtonText]}>{props.button.text}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
@ -157,6 +185,8 @@ MultipleStepsListItem.propTypes = {
|
||||||
checked: PropTypes.bool,
|
checked: PropTypes.bool,
|
||||||
leftText: PropTypes.string,
|
leftText: PropTypes.string,
|
||||||
showActivityIndicator: PropTypes.bool,
|
showActivityIndicator: PropTypes.bool,
|
||||||
|
useActionSheet: PropTypes.bool,
|
||||||
|
actionSheetOptions: PropTypes.shape(ActionSheetOptions),
|
||||||
dashes: PropTypes.number,
|
dashes: PropTypes.number,
|
||||||
button: PropTypes.shape({
|
button: PropTypes.shape({
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
|
|
11
screen/ActionSheet.common.ts
Normal file
11
screen/ActionSheet.common.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// ActionSheet.common.ts
|
||||||
|
export interface ActionSheetOptions {
|
||||||
|
title?: string;
|
||||||
|
message?: string;
|
||||||
|
options: string[]; // Array of button labels.
|
||||||
|
destructiveButtonIndex?: number;
|
||||||
|
cancelButtonIndex?: number;
|
||||||
|
anchor?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CompletionCallback = (buttonIndex: number) => void;
|
|
@ -1,10 +0,0 @@
|
||||||
import { ActionSheetIOS, InteractionManager } from 'react-native';
|
|
||||||
|
|
||||||
export default class ActionSheet {
|
|
||||||
static showActionSheetWithOptions(options, completion) {
|
|
||||||
ActionSheetIOS.dismissActionSheet();
|
|
||||||
InteractionManager.runAfterInteractions(() => {
|
|
||||||
ActionSheetIOS.showActionSheetWithOptions(options, completion);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
15
screen/ActionSheet.ios.ts
Normal file
15
screen/ActionSheet.ios.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// ActionSheet.ios.ts
|
||||||
|
import { ActionSheetIOS, InteractionManager } from 'react-native';
|
||||||
|
import { ActionSheetOptions, CompletionCallback } from './ActionSheet.common';
|
||||||
|
|
||||||
|
export default class ActionSheet {
|
||||||
|
static showActionSheetWithOptions(options: ActionSheetOptions, completion: CompletionCallback): void {
|
||||||
|
InteractionManager.runAfterInteractions(() => {
|
||||||
|
const iosOptions = {
|
||||||
|
...options,
|
||||||
|
anchor: options.anchor,
|
||||||
|
};
|
||||||
|
ActionSheetIOS.showActionSheetWithOptions(iosOptions, completion);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
import { Alert, InteractionManager } from 'react-native';
|
|
||||||
|
|
||||||
export default class ActionSheet {
|
|
||||||
static showActionSheetWithOptions(options) {
|
|
||||||
InteractionManager.runAfterInteractions(() => {
|
|
||||||
Alert.alert(options.title, options.message, options.buttons, { cancelable: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
26
screen/ActionSheet.ts
Normal file
26
screen/ActionSheet.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// ActionSheet.ts
|
||||||
|
import { Alert, InteractionManager } from 'react-native';
|
||||||
|
import { ActionSheetOptions, CompletionCallback } from './ActionSheet.common';
|
||||||
|
|
||||||
|
export default class ActionSheet {
|
||||||
|
static showActionSheetWithOptions(options: ActionSheetOptions, completion: CompletionCallback): void {
|
||||||
|
InteractionManager.runAfterInteractions(() => {
|
||||||
|
const alertOptions = options.options.map((option, index) => {
|
||||||
|
let style: 'default' | 'cancel' | 'destructive' = 'default';
|
||||||
|
if (index === options.destructiveButtonIndex) {
|
||||||
|
style = 'destructive';
|
||||||
|
} else if (index === options.cancelButtonIndex) {
|
||||||
|
style = 'cancel';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
text: option,
|
||||||
|
onPress: () => completion(index),
|
||||||
|
style,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
Alert.alert(options.title || '', options.message || '', alertOptions, { cancelable: !!options.cancelButtonIndex });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Alert,
|
|
||||||
FlatList,
|
FlatList,
|
||||||
InteractionManager,
|
InteractionManager,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
|
@ -48,6 +47,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import { scanQrHelper } from '../../helpers/scan-qr';
|
import { scanQrHelper } from '../../helpers/scan-qr';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
|
import { isDesktop } from '../../blue_modules/environment';
|
||||||
const fs = require('../../blue_modules/fs');
|
const fs = require('../../blue_modules/fs');
|
||||||
const prompt = require('../../helpers/prompt');
|
const prompt = require('../../helpers/prompt');
|
||||||
|
|
||||||
|
@ -357,45 +357,43 @@ const ViewEditMultisigCosigners = ({ route }: Props) => {
|
||||||
dashes={MultipleStepsListItemDashType.topAndBottom}
|
dashes={MultipleStepsListItemDashType.topAndBottom}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* destructiveButtonIndex and cancelButtonIndex are different numbers on Mac Catalyst and mobile */}
|
||||||
<MultipleStepsListItem
|
<MultipleStepsListItem
|
||||||
|
useActionSheet
|
||||||
|
actionSheetOptions={{
|
||||||
|
options: isDesktop ? [loc.multisig.confirm, loc._.cancel] : ['', loc.multisig.confirm, loc._.cancel],
|
||||||
|
title: loc._.seed,
|
||||||
|
message: loc.multisig.are_you_sure_seed_will_be_lost,
|
||||||
|
cancelButtonIndex: isDesktop ? 1 : 0,
|
||||||
|
destructiveButtonIndex: isDesktop ? 0 : 1,
|
||||||
|
}}
|
||||||
showActivityIndicator={vaultKeyData.keyIndex === el.index + 1 && vaultKeyData.isLoading}
|
showActivityIndicator={vaultKeyData.keyIndex === el.index + 1 && vaultKeyData.isLoading}
|
||||||
dashes={el.index === length - 1 ? MultipleStepsListItemDashType.top : MultipleStepsListItemDashType.topAndBottom}
|
dashes={el.index === length - 1 ? MultipleStepsListItemDashType.top : MultipleStepsListItemDashType.topAndBottom}
|
||||||
button={{
|
button={{
|
||||||
text: loc.multisig.forget_this_seed,
|
text: loc.multisig.forget_this_seed,
|
||||||
disabled: vaultKeyData.isLoading,
|
disabled: vaultKeyData.isLoading,
|
||||||
buttonType: MultipleStepsListItemButtohType.full,
|
buttonType: MultipleStepsListItemButtohType.full,
|
||||||
onPress: () => {
|
|
||||||
Alert.alert(
|
onPress: buttonIndex => {
|
||||||
loc._.seed,
|
if ((isDesktop && buttonIndex === 1) || (!isDesktop && buttonIndex === 2)) return;
|
||||||
loc.multisig.are_you_sure_seed_will_be_lost,
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||||
[
|
setVaultKeyData({
|
||||||
{
|
...vaultKeyData,
|
||||||
text: loc._.ok,
|
isLoading: true,
|
||||||
onPress: () => {
|
keyIndex: el.index + 1,
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
});
|
||||||
setVaultKeyData({
|
setTimeout(
|
||||||
...vaultKeyData,
|
() =>
|
||||||
isLoading: true,
|
xpubInsteadOfSeed(el.index + 1).finally(() => {
|
||||||
keyIndex: el.index + 1,
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||||
});
|
setVaultKeyData({
|
||||||
setTimeout(
|
...vaultKeyData,
|
||||||
() =>
|
isLoading: false,
|
||||||
xpubInsteadOfSeed(el.index + 1).finally(() => {
|
keyIndex: el.index + 1,
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
});
|
||||||
setVaultKeyData({
|
}),
|
||||||
...vaultKeyData,
|
100,
|
||||||
isLoading: false,
|
|
||||||
keyIndex: el.index + 1,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
100,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
style: 'destructive',
|
|
||||||
},
|
|
||||||
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
|
|
||||||
],
|
|
||||||
{ cancelable: false },
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
Loading…
Add table
Reference in a new issue