mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-22 02:24:30 +00:00
encode resharer names in resharer config
This commit is contained in:
parent
7455ab55f5
commit
76844a562b
11 changed files with 143 additions and 460 deletions
|
@ -63,7 +63,9 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
|
|||
if (mounted) {
|
||||
final result = Frost.beginResharer(
|
||||
serializedKeys: serializedKeys!,
|
||||
config: ref.read(pFrostResharingData).resharerConfig!,
|
||||
config: Frost.decodeRConfig(
|
||||
ref.read(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
);
|
||||
|
||||
ref.read(pFrostResharingData).startResharerData = result;
|
||||
|
@ -216,6 +218,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
|
|||
.read(pFrostResharingData)
|
||||
.configData!
|
||||
.resharers
|
||||
.values
|
||||
.contains(myOldIndex);
|
||||
super.initState();
|
||||
}
|
||||
|
@ -236,7 +239,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
QrImageView(
|
||||
data: ref.watch(pFrostResharingData).resharerConfig!,
|
||||
data: ref.watch(pFrostResharingData).resharerRConfig!,
|
||||
size: 220,
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
|
@ -252,13 +255,13 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
|
|||
),
|
||||
DetailItem(
|
||||
title: "Config",
|
||||
detail: ref.watch(pFrostResharingData).resharerConfig!,
|
||||
detail: ref.watch(pFrostResharingData).resharerRConfig!,
|
||||
button: Util.isDesktop
|
||||
? IconCopyButton(
|
||||
data: ref.watch(pFrostResharingData).resharerConfig!,
|
||||
data: ref.watch(pFrostResharingData).resharerRConfig!,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: ref.watch(pFrostResharingData).resharerConfig!,
|
||||
data: ref.watch(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
|
|
|
@ -63,13 +63,16 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
|
|||
|
||||
ref.read(pFrostResharingData).reset();
|
||||
ref.read(pFrostResharingData).myName = frostInfo.myName;
|
||||
ref.read(pFrostResharingData).resharerConfig = configFieldController.text;
|
||||
ref.read(pFrostResharingData).resharerRConfig =
|
||||
configFieldController.text;
|
||||
|
||||
String? salt;
|
||||
try {
|
||||
salt = Format.uint8listToString(
|
||||
resharerSalt(
|
||||
resharerConfig: ref.read(pFrostResharingData).resharerConfig!,
|
||||
resharerConfig: Frost.decodeRConfig(
|
||||
ref.read(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (_) {
|
||||
|
@ -97,7 +100,9 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
|
|||
if (mounted) {
|
||||
final result = Frost.beginResharer(
|
||||
serializedKeys: serializedKeys!,
|
||||
config: ref.read(pFrostResharingData).resharerConfig!,
|
||||
config: Frost.decodeRConfig(
|
||||
ref.read(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
);
|
||||
|
||||
ref.read(pFrostResharingData).startResharerData = result;
|
||||
|
|
|
@ -176,7 +176,7 @@ class _FrostReshareStep1cState extends ConsumerState<FrostReshareStep1c> {
|
|||
ref.read(pFrostResharingData).reset();
|
||||
ref.read(pFrostResharingData).myName =
|
||||
myNameFieldController.text;
|
||||
ref.read(pFrostResharingData).resharerConfig =
|
||||
ref.read(pFrostResharingData).resharerRConfig =
|
||||
configFieldController.text;
|
||||
|
||||
if (!ref
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
||||
|
@ -11,20 +9,14 @@ import 'package:stackwallet/providers/db/main_db_provider.dart';
|
|||
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
||||
import 'package:stackwallet/services/frost.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/detail_item.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/textfields/frost_step_field.dart';
|
||||
|
||||
class FrostReshareStep2abd extends ConsumerStatefulWidget {
|
||||
const FrostReshareStep2abd({super.key});
|
||||
|
@ -41,7 +33,7 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
|
|||
final List<TextEditingController> controllers = [];
|
||||
final List<FocusNode> focusNodes = [];
|
||||
|
||||
late final List<int> resharerIndexes;
|
||||
late final Map<String, int> resharers;
|
||||
late final int myResharerIndexIndex;
|
||||
late final String myResharerStart;
|
||||
late final bool amOutgoingParticipant;
|
||||
|
@ -67,7 +59,9 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
|
|||
|
||||
final result = Frost.beginReshared(
|
||||
myName: ref.read(pFrostResharingData).myName!,
|
||||
resharerConfig: ref.read(pFrostResharingData).resharerConfig!,
|
||||
resharerConfig: Frost.decodeRConfig(
|
||||
ref.read(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
resharerStarts: resharerStarts,
|
||||
);
|
||||
|
||||
|
@ -116,11 +110,11 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
|
|||
myResharerStart =
|
||||
ref.read(pFrostResharingData).startResharerData!.resharerStart;
|
||||
|
||||
resharerIndexes = ref.read(pFrostResharingData).configData!.resharers;
|
||||
myResharerIndexIndex = resharerIndexes.indexOf(myOldIndex);
|
||||
resharers = ref.read(pFrostResharingData).configData!.resharers;
|
||||
myResharerIndexIndex = resharers.values.toList().indexOf(myOldIndex);
|
||||
if (myResharerIndexIndex >= 0) {
|
||||
// remove my name for now as we don't need a text field for it
|
||||
resharerIndexes.removeAt(myResharerIndexIndex);
|
||||
resharers.remove(ref.read(pFrostResharingData).myName!);
|
||||
}
|
||||
|
||||
amOutgoingParticipant = !ref
|
||||
|
@ -129,7 +123,7 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
|
|||
.newParticipants
|
||||
.contains(ref.read(pFrostResharingData).myName!);
|
||||
|
||||
for (int i = 0; i < resharerIndexes.length; i++) {
|
||||
for (int i = 0; i < resharers.length; i++) {
|
||||
controllers.add(TextEditingController());
|
||||
focusNodes.add(FocusNode());
|
||||
fieldIsEmptyFlags.add(true);
|
||||
|
@ -192,137 +186,20 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < resharerIndexes.length; i++)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
key: Key("frostResharerTextFieldKey_$i"),
|
||||
for (int i = 0; i < resharers.length; i++)
|
||||
FrostStepField(
|
||||
controller: controllers[i],
|
||||
focusNode: focusNodes[i],
|
||||
readOnly: false,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
style: STextStyles.field(context),
|
||||
showQrScanOption: true,
|
||||
label: resharers.keys.elementAt(i),
|
||||
hint: "Enter "
|
||||
"${resharers.keys.elementAt(i)}"
|
||||
"'s resharer",
|
||||
onChanged: (_) {
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
fieldIsEmptyFlags[i] = controllers[i].text.isEmpty;
|
||||
});
|
||||
},
|
||||
decoration: standardInputDecoration(
|
||||
"Enter index "
|
||||
"${resharerIndexes[i]}"
|
||||
"'s resharer",
|
||||
focusNodes[i],
|
||||
context,
|
||||
).copyWith(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
top: 6,
|
||||
bottom: 8,
|
||||
right: 5,
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: fieldIsEmptyFlags[i]
|
||||
? const EdgeInsets.only(right: 8)
|
||||
: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
!fieldIsEmptyFlags[i]
|
||||
? TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Clear Button. Clears The Resharer Field Input.",
|
||||
key: Key(
|
||||
"frostResharerClearButtonKey_$i"),
|
||||
onTap: () {
|
||||
controllers[i].text = "";
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] = true;
|
||||
});
|
||||
},
|
||||
child: const XIcon(),
|
||||
)
|
||||
: TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Paste Button. Pastes From Clipboard To Resharer Field Input.",
|
||||
key: Key(
|
||||
"frostResharerPasteButtonKey_$i"),
|
||||
onTap: () async {
|
||||
final ClipboardData? data =
|
||||
await Clipboard.getData(
|
||||
Clipboard.kTextPlain);
|
||||
if (data?.text != null &&
|
||||
data!.text!.isNotEmpty) {
|
||||
controllers[i].text =
|
||||
data.text!.trim();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
});
|
||||
},
|
||||
child: fieldIsEmptyFlags[i]
|
||||
? const ClipboardIcon()
|
||||
: const XIcon(),
|
||||
),
|
||||
if (fieldIsEmptyFlags[i])
|
||||
TextFieldIconButton(
|
||||
semanticsLabel: "Scan QR Button. "
|
||||
"Opens Camera For Scanning QR Code.",
|
||||
key: Key(
|
||||
"frostCommitmentsScanQrButtonKey_$i"),
|
||||
onTap: () async {
|
||||
try {
|
||||
if (FocusScope.of(context)
|
||||
.hasFocus) {
|
||||
FocusScope.of(context).unfocus();
|
||||
await Future<void>.delayed(
|
||||
const Duration(
|
||||
milliseconds: 75));
|
||||
}
|
||||
|
||||
final qrResult =
|
||||
await BarcodeScanner.scan();
|
||||
|
||||
controllers[i].text =
|
||||
qrResult.rawContent;
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
});
|
||||
} on PlatformException catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to get camera permissions "
|
||||
"while trying to scan qr code: $e\n$s",
|
||||
level: LogLevel.Warning,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const QrCodeIcon(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,23 +1,15 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
||||
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
||||
import 'package:stackwallet/services/frost.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/textfields/frost_step_field.dart';
|
||||
|
||||
class FrostReshareStep2c extends ConsumerStatefulWidget {
|
||||
const FrostReshareStep2c({super.key});
|
||||
|
@ -33,7 +25,7 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
|
|||
final List<TextEditingController> controllers = [];
|
||||
final List<FocusNode> focusNodes = [];
|
||||
|
||||
late final List<int> resharerIndexes;
|
||||
late final Map<String, int> resharers;
|
||||
|
||||
final List<bool> fieldIsEmptyFlags = [];
|
||||
|
||||
|
@ -50,7 +42,9 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
|
|||
|
||||
final result = Frost.beginReshared(
|
||||
myName: ref.read(pFrostResharingData).myName!,
|
||||
resharerConfig: ref.read(pFrostResharingData).resharerConfig!,
|
||||
resharerConfig: Frost.decodeRConfig(
|
||||
ref.read(pFrostResharingData).resharerRConfig!,
|
||||
),
|
||||
resharerStarts: resharerStarts,
|
||||
);
|
||||
|
||||
|
@ -84,9 +78,9 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
resharerIndexes = ref.read(pFrostResharingData).configData!.resharers;
|
||||
resharers = ref.read(pFrostResharingData).configData!.resharers;
|
||||
|
||||
for (int i = 0; i < resharerIndexes.length; i++) {
|
||||
for (int i = 0; i < resharers.length; i++) {
|
||||
controllers.add(TextEditingController());
|
||||
focusNodes.add(FocusNode());
|
||||
fieldIsEmptyFlags.add(true);
|
||||
|
@ -115,137 +109,23 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < resharerIndexes.length; i++)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < resharers.length; i++)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
key: Key("frostResharerTextFieldKey_$i"),
|
||||
child: FrostStepField(
|
||||
controller: controllers[i],
|
||||
focusNode: focusNodes[i],
|
||||
readOnly: false,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
style: STextStyles.field(context),
|
||||
showQrScanOption: true,
|
||||
label: resharers.keys.elementAt(i),
|
||||
hint: "Enter "
|
||||
"${resharers.keys.elementAt(i)}"
|
||||
"'s resharer",
|
||||
onChanged: (_) {
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
fieldIsEmptyFlags[i] = controllers[i].text.isEmpty;
|
||||
});
|
||||
},
|
||||
decoration: standardInputDecoration(
|
||||
"Enter index "
|
||||
"${resharerIndexes[i]}"
|
||||
"'s resharer",
|
||||
focusNodes[i],
|
||||
context,
|
||||
).copyWith(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
top: 6,
|
||||
bottom: 8,
|
||||
right: 5,
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: fieldIsEmptyFlags[i]
|
||||
? const EdgeInsets.only(right: 8)
|
||||
: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
!fieldIsEmptyFlags[i]
|
||||
? TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Clear Button. Clears The Resharer Field Input.",
|
||||
key: Key(
|
||||
"frostResharerClearButtonKey_$i"),
|
||||
onTap: () {
|
||||
controllers[i].text = "";
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] = true;
|
||||
});
|
||||
},
|
||||
child: const XIcon(),
|
||||
)
|
||||
: TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Paste Button. Pastes From Clipboard To Resharer Field Input.",
|
||||
key: Key(
|
||||
"frostResharerPasteButtonKey_$i"),
|
||||
onTap: () async {
|
||||
final ClipboardData? data =
|
||||
await Clipboard.getData(
|
||||
Clipboard.kTextPlain);
|
||||
if (data?.text != null &&
|
||||
data!.text!.isNotEmpty) {
|
||||
controllers[i].text =
|
||||
data.text!.trim();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
});
|
||||
},
|
||||
child: fieldIsEmptyFlags[i]
|
||||
? const ClipboardIcon()
|
||||
: const XIcon(),
|
||||
),
|
||||
if (fieldIsEmptyFlags[i])
|
||||
TextFieldIconButton(
|
||||
semanticsLabel: "Scan QR Button. "
|
||||
"Opens Camera For Scanning QR Code.",
|
||||
key: Key(
|
||||
"frostCommitmentsScanQrButtonKey_$i"),
|
||||
onTap: () async {
|
||||
try {
|
||||
if (FocusScope.of(context)
|
||||
.hasFocus) {
|
||||
FocusScope.of(context).unfocus();
|
||||
await Future<void>.delayed(
|
||||
const Duration(
|
||||
milliseconds: 75));
|
||||
}
|
||||
|
||||
final qrResult =
|
||||
await BarcodeScanner.scan();
|
||||
|
||||
controllers[i].text =
|
||||
qrResult.rawContent;
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
});
|
||||
} on PlatformException catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to get camera permissions "
|
||||
"while trying to scan qr code: $e\n$s",
|
||||
level: LogLevel.Warning,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const QrCodeIcon(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import 'dart:ffi';
|
||||
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
||||
|
@ -13,20 +11,14 @@ import 'package:stackwallet/providers/db/main_db_provider.dart';
|
|||
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
||||
import 'package:stackwallet/services/frost.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/detail_item.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/textfields/frost_step_field.dart';
|
||||
|
||||
// was FinishResharingView
|
||||
class FrostReshareStep4 extends ConsumerStatefulWidget {
|
||||
|
@ -43,7 +35,7 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
|
|||
final List<TextEditingController> controllers = [];
|
||||
final List<FocusNode> focusNodes = [];
|
||||
|
||||
late final List<int> resharerIndexes;
|
||||
late final Map<String, int> resharers;
|
||||
late final String myName;
|
||||
late final int? myResharerIndexIndex;
|
||||
late final String? myResharerComplete;
|
||||
|
@ -118,7 +110,7 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
|
|||
|
||||
myName = ref.read(pFrostResharingData).myName!;
|
||||
|
||||
resharerIndexes = ref.read(pFrostResharingData).configData!.resharers;
|
||||
resharers = ref.read(pFrostResharingData).configData!.resharers;
|
||||
|
||||
if (amNewParticipant) {
|
||||
myResharerComplete = null;
|
||||
|
@ -135,10 +127,10 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
|
|||
final myOldIndex =
|
||||
frostInfo.participants.indexOf(ref.read(pFrostResharingData).myName!);
|
||||
|
||||
myResharerIndexIndex = resharerIndexes.indexOf(myOldIndex);
|
||||
myResharerIndexIndex = resharers.values.toList().indexOf(myOldIndex);
|
||||
if (myResharerIndexIndex! >= 0) {
|
||||
// remove my name for now as we don't need a text field for it
|
||||
resharerIndexes.removeAt(myResharerIndexIndex!);
|
||||
resharers.remove(ref.read(pFrostResharingData).myName!);
|
||||
}
|
||||
|
||||
amOutgoingParticipant = !ref
|
||||
|
@ -148,7 +140,7 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
|
|||
.contains(ref.read(pFrostResharingData).myName!);
|
||||
}
|
||||
|
||||
for (int i = 0; i < resharerIndexes.length; i++) {
|
||||
for (int i = 0; i < resharers.length; i++) {
|
||||
controllers.add(TextEditingController());
|
||||
focusNodes.add(FocusNode());
|
||||
fieldIsEmptyFlags.add(true);
|
||||
|
@ -216,139 +208,23 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < resharerIndexes.length; i++)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < resharers.length; i++)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
key: Key("frostEncryptionKeyTextFieldKey_$i"),
|
||||
child: FrostStepField(
|
||||
controller: controllers[i],
|
||||
focusNode: focusNodes[i],
|
||||
readOnly: false,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
style: STextStyles.field(context),
|
||||
showQrScanOption: true,
|
||||
label: resharers.keys.elementAt(i),
|
||||
hint: "Enter "
|
||||
"${resharers.keys.elementAt(i)}"
|
||||
"'s resharer",
|
||||
onChanged: (_) {
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
fieldIsEmptyFlags[i] = controllers[i].text.isEmpty;
|
||||
});
|
||||
},
|
||||
decoration: standardInputDecoration(
|
||||
"Enter index "
|
||||
"${resharerIndexes[i]}"
|
||||
"'s resharer complete",
|
||||
focusNodes[i],
|
||||
context,
|
||||
).copyWith(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
top: 6,
|
||||
bottom: 8,
|
||||
right: 5,
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: fieldIsEmptyFlags[i]
|
||||
? const EdgeInsets.only(right: 8)
|
||||
: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
!fieldIsEmptyFlags[i]
|
||||
? TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Clear Button. Clears The Encryption Key Field Input.",
|
||||
key: Key(
|
||||
"frostEncryptionKeyClearButtonKey_$i"),
|
||||
onTap: () {
|
||||
controllers[i].text = "";
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] = true;
|
||||
});
|
||||
},
|
||||
child: const XIcon(),
|
||||
)
|
||||
: TextFieldIconButton(
|
||||
semanticsLabel:
|
||||
"Paste Button. Pastes From Clipboard To Encryption Key Field Input.",
|
||||
key: Key(
|
||||
"frostEncryptionKeyPasteButtonKey_$i"),
|
||||
onTap: () async {
|
||||
final ClipboardData? data =
|
||||
await Clipboard.getData(
|
||||
Clipboard.kTextPlain);
|
||||
if (data?.text != null &&
|
||||
data!.text!.isNotEmpty) {
|
||||
controllers[i].text =
|
||||
data.text!.trim();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i]
|
||||
.text
|
||||
.isEmpty;
|
||||
});
|
||||
},
|
||||
child: fieldIsEmptyFlags[i]
|
||||
? const ClipboardIcon()
|
||||
: const XIcon(),
|
||||
),
|
||||
if (fieldIsEmptyFlags[i])
|
||||
TextFieldIconButton(
|
||||
semanticsLabel: "Scan QR Button. "
|
||||
"Opens Camera For Scanning QR Code.",
|
||||
key: Key("frostScanQrButtonKey_$i"),
|
||||
onTap: () async {
|
||||
try {
|
||||
if (FocusScope.of(context)
|
||||
.hasFocus) {
|
||||
FocusScope.of(context)
|
||||
.unfocus();
|
||||
await Future<void>.delayed(
|
||||
const Duration(
|
||||
milliseconds: 75));
|
||||
}
|
||||
|
||||
final qrResult =
|
||||
await BarcodeScanner.scan();
|
||||
|
||||
controllers[i].text =
|
||||
qrResult.rawContent;
|
||||
|
||||
setState(() {
|
||||
fieldIsEmptyFlags[i] =
|
||||
controllers[i].text.isEmpty;
|
||||
});
|
||||
} on PlatformException catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to get camera permissions "
|
||||
"while trying to scan qr code: $e\n$s",
|
||||
level: LogLevel.Warning,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const QrCodeIcon(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -37,7 +37,7 @@ final class CompleteReshareConfigView extends ConsumerStatefulWidget {
|
|||
static const String routeName = "/completeReshareConfigView";
|
||||
|
||||
final String walletId;
|
||||
final List<int> resharers;
|
||||
final Map<String, int> resharers;
|
||||
|
||||
@override
|
||||
ConsumerState<CompleteReshareConfigView> createState() =>
|
||||
|
@ -91,7 +91,7 @@ class _CompleteReshareConfigViewState
|
|||
|
||||
final config = Frost.createResharerConfig(
|
||||
newThreshold: int.parse(_newThresholdController.text),
|
||||
resharers: widget.resharers,
|
||||
resharers: widget.resharers.values.toList(),
|
||||
newParticipants: newParticipants,
|
||||
);
|
||||
|
||||
|
@ -121,7 +121,10 @@ class _CompleteReshareConfigViewState
|
|||
}
|
||||
|
||||
ref.read(pFrostResharingData).myName = myName;
|
||||
ref.read(pFrostResharingData).resharerConfig = config;
|
||||
ref.read(pFrostResharingData).resharerRConfig = Frost.encodeRConfig(
|
||||
config,
|
||||
widget.resharers,
|
||||
);
|
||||
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as BitcoinFrostWallet;
|
||||
|
|
|
@ -234,10 +234,11 @@ class _BeginReshareConfigViewState
|
|||
onPressed: () async {
|
||||
// include self now
|
||||
selectedParticipants.add(myName);
|
||||
final List<int> resharers = [];
|
||||
|
||||
final Map<String, int> resharers = {};
|
||||
|
||||
for (final name in selectedParticipants) {
|
||||
resharers.add(originalParticipants.indexOf(name));
|
||||
resharers[name] = originalParticipants.indexOf(name);
|
||||
}
|
||||
|
||||
await Navigator.of(context).pushNamed(
|
||||
|
|
|
@ -60,13 +60,14 @@ class _ResharingData {
|
|||
IncompleteFrostWallet? incompleteWallet;
|
||||
|
||||
// resharer encoded config string
|
||||
String? resharerConfig;
|
||||
String? resharerRConfig;
|
||||
|
||||
({
|
||||
int newThreshold,
|
||||
List<int> resharers,
|
||||
Map<String, int> resharers,
|
||||
List<String> newParticipants,
|
||||
})? get configData => resharerConfig != null
|
||||
? Frost.extractResharerConfigData(resharerConfig: resharerConfig!)
|
||||
})? get configData => resharerRConfig != null
|
||||
? Frost.extractResharerConfigData(rConfig: resharerRConfig!)
|
||||
: null;
|
||||
|
||||
// resharer start string (for sharing) and machine
|
||||
|
@ -93,7 +94,7 @@ class _ResharingData {
|
|||
|
||||
// reset/clear all data
|
||||
void reset() {
|
||||
resharerConfig = null;
|
||||
resharerRConfig = null;
|
||||
startResharerData = null;
|
||||
startResharedData = null;
|
||||
resharerComplete = null;
|
||||
|
|
|
@ -542,7 +542,7 @@ class RouteGenerator {
|
|||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||
|
||||
case CompleteReshareConfigView.routeName:
|
||||
if (args is ({String walletId, List<int> resharers})) {
|
||||
if (args is ({String walletId, Map<String, int> resharers})) {
|
||||
return getRoute(
|
||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||
builder: (_) => CompleteReshareConfigView(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
@ -551,11 +552,14 @@ abstract class Frost {
|
|||
|
||||
static ({
|
||||
int newThreshold,
|
||||
List<int> resharers,
|
||||
Map<String, int> resharers,
|
||||
List<String> newParticipants,
|
||||
}) extractResharerConfigData({
|
||||
required String resharerConfig,
|
||||
required String rConfig,
|
||||
}) {
|
||||
final decoded = _decodeRConfigWithResharers(rConfig);
|
||||
final resharerConfig = decoded.config;
|
||||
|
||||
try {
|
||||
final newThreshold = resharerNewThreshold(
|
||||
resharerConfigPointer: decodedResharerConfig(
|
||||
|
@ -597,9 +601,17 @@ abstract class Frost {
|
|||
);
|
||||
}
|
||||
|
||||
final Map<String, int> resharersMap = {};
|
||||
|
||||
for (final resharer in resharers) {
|
||||
resharersMap[decoded.resharers.entries
|
||||
.firstWhere((e) => e.value == resharer)
|
||||
.key] = resharer;
|
||||
}
|
||||
|
||||
return (
|
||||
newThreshold: newThreshold,
|
||||
resharers: resharers,
|
||||
resharers: resharersMap,
|
||||
newParticipants: newParticipants,
|
||||
);
|
||||
} catch (e, s) {
|
||||
|
@ -610,4 +622,29 @@ abstract class Frost {
|
|||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static String encodeRConfig(
|
||||
String config,
|
||||
Map<String, int> resharers,
|
||||
) {
|
||||
return base64Encode("$config@${jsonEncode(resharers)}".toUint8ListFromUtf8);
|
||||
}
|
||||
|
||||
static String decodeRConfig(
|
||||
String rConfig,
|
||||
) {
|
||||
return base64Decode(rConfig).toUtf8String.split("@").first;
|
||||
}
|
||||
|
||||
static ({Map<String, int> resharers, String config})
|
||||
_decodeRConfigWithResharers(
|
||||
String rConfig,
|
||||
) {
|
||||
final parts = base64Decode(rConfig).toUtf8String.split("@");
|
||||
|
||||
final config = parts[0];
|
||||
final resharers = Map<String, int>.from(jsonDecode(parts[1]) as Map);
|
||||
|
||||
return (resharers: resharers, config: config);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue