Skip to content
Snippets Groups Projects
Commit 8170c5b4 authored by vjrj's avatar vjrj
Browse files

More work with multi-card support

parent 5a6bd007
No related branches found
No related tags found
No related merge requests found
......@@ -168,21 +168,25 @@ class SharedPreferencesHelper with ChangeNotifier {
}
}
bool has(String wallet) {
bool has(String pubKey) {
for (final CesiumCard card in cesiumCards) {
if (card.pubKey == wallet) {
if (card.pubKey == extractPublicKey(pubKey) || card.pubKey == pubKey) {
return true;
}
}
return false;
}
bool hasVolatile() {
return cesiumVolatileCards.containsKey(extractPublicKey(getPubKey()));
}
void addCesiumVolatileCard(CesiumWallet cesiumWallet) {
cesiumVolatileCards[cesiumWallet.pubkey] = cesiumWallet;
}
bool isG1nkgoCard([CesiumCard? ocard]) {
final CesiumCard card = ocard ?? cesiumCards[getCurrentWalletIndex()];
bool isG1nkgoCard([CesiumCard? otherCard]) {
final CesiumCard card = otherCard ?? cesiumCards[getCurrentWalletIndex()];
return card.seed.isNotEmpty;
}
}
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import '../widgets/fifth_screen/import_dialog.dart';
class Sandbox extends StatefulWidget {
const Sandbox({super.key});
......@@ -15,12 +13,7 @@ class _SandboxState extends State<Sandbox> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: TextButton(
onPressed: () {
showImportCesiumWalletDialog(
context, '6DrGg8cftpkgffv4Y4Lse9HSjgc8coEQor3yvMPHAnVH:HCT');
},
child: const Text('Auth')),
body: TextButton(onPressed: () {}, child: const Text('Auth')),
);
}
}
......@@ -17,14 +17,10 @@ import 'form_error_widget.dart';
class CesiumAddDialog extends StatefulWidget {
const CesiumAddDialog(
{super.key,
required this.cardName,
required this.publicKey,
required this.onAccept});
{super.key, required this.cardName, required this.publicKey});
final String cardName;
final String publicKey;
final VoidCallback onAccept;
@override
State<CesiumAddDialog> createState() => _CesiumAddDialogState();
......@@ -107,7 +103,7 @@ class _CesiumAddDialogState extends State<CesiumAddDialog> {
TextButton(
child: Text(tr('cancel')),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop(false);
},
),
TextButton(
......@@ -134,12 +130,15 @@ class _CesiumAddDialogState extends State<CesiumAddDialog> {
pubKey: extractPublicKey(widget.publicKey),
seed: '',
theme: CreditCardThemes.themes[Random().nextInt(10)]);
SharedPreferencesHelper().addCesiumCard(card);
if (!SharedPreferencesHelper()
.has(extractPublicKey(widget.publicKey))) {
SharedPreferencesHelper().addCesiumCard(card);
}
SharedPreferencesHelper().addCesiumVolatileCard(wallet);
SharedPreferencesHelper().selectCurrentWallet(card);
context.read<BottomNavCubit>().updateIndex(0);
_feedbackNotifier.value = '';
Navigator.of(context).pop();
Navigator.of(context).pop(true);
}
},
child: _isProcessing
......
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:easy_localization/easy_localization.dart';
import 'package:filesystem_picker/filesystem_picker.dart';
......@@ -12,8 +11,6 @@ import 'package:pattern_lock/pattern_lock.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:universal_html/html.dart' as html;
import '../../../data/models/cesium_card.dart';
import '../../../data/models/credit_card_themes.dart';
import '../../../data/models/transaction_cubit.dart';
import '../../../g1/g1_helper.dart';
import '../../../shared_prefs_helper.dart';
......@@ -48,7 +45,7 @@ class _ImportDialogState extends State<ImportDialog> {
snapshot.data!.isNotEmpty) {
final String keyEncString = snapshot.data!;
final Map<String, dynamic> keyJson =
jsonDecode(keyEncString) as Map<String, dynamic>;
jsonDecode(keyEncString) as Map<String, dynamic>;
final String keyEncrypted = keyJson['key'] as String;
// final Uint8List keyBase64 = base64Decode(keyEncrypted);
return Scaffold(
......@@ -77,16 +74,16 @@ class _ImportDialogState extends State<ImportDialog> {
try {
// try to decrypt
final Map<String, dynamic> keys =
decryptJsonForImport(
keyEncrypted, pattern.join());
decryptJsonForImport(
keyEncrypted, pattern.join());
final bool? confirm = await confirmImport(context);
if (confirm != null && confirm) {
try {
final dynamic cesiumCards = keys['cesiumCards'];
if (cesiumCards != null) {
final List<dynamic> cesiumCardList =
jsonDecode(cesiumCards as String)
as List<dynamic>;
jsonDecode(cesiumCards as String)
as List<dynamic>;
// ignore: avoid_function_literals_in_foreach_calls
cesiumCardList.forEach((dynamic cesiumCard) {
importWalletToSharedPrefs(
......@@ -155,9 +152,9 @@ class _ImportDialogState extends State<ImportDialog> {
final dynamic pub = cesiumCard['pub'];
SharedPreferencesHelper().addCesiumCard(SharedPreferencesHelper()
.buildCesiumCard(
pubKey:
pub != null ? pub as String : cesiumCard['pubKey'] as String,
seed: cesiumCard['seed'] as String));
pubKey:
pub != null ? pub as String : cesiumCard['pubKey'] as String,
seed: cesiumCard['seed'] as String));
}
Future<String> _importWallet(BuildContext context) async {
......@@ -215,8 +212,7 @@ class _ImportDialogState extends State<ImportDialog> {
Future<String> _importWalletWeb(BuildContext context) async {
final Completer<String> completer = Completer<String>();
final html.InputElement input = html.InputElement()
..type = 'file';
final html.InputElement input = html.InputElement()..type = 'file';
input.multiple = false;
input.accept = '.json'; // limit file types
......@@ -251,9 +247,7 @@ class _ImportDialogState extends State<ImportDialog> {
}
Future<bool?> confirmImport(BuildContext context) async {
final bool hasBalance = context
.read<TransactionCubit>()
.balance > 0;
final bool hasBalance = context.read<TransactionCubit>().balance > 0;
return showDialog<bool>(
context: context,
builder: (BuildContext context) {
......@@ -317,23 +311,14 @@ Future<void> showSelectImportMethodDialog(BuildContext context) async {
}
}
void showImportCesiumWalletDialog(BuildContext context, String wallet) {
showDialog<void>(
Future<bool?> showImportCesiumWalletDialog(
BuildContext context, String wallet) {
return showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return CesiumAddDialog(
onAccept: () {
SharedPreferencesHelper().addCesiumCard(CesiumCard(
name: '',
theme:
CreditCardThemes.themes[Random().nextInt(10)],
pubKey: extractPublicKey(wallet),
seed: ''));
},
cardName: humanizePubKey(wallet),
publicKey: wallet,
);
cardName: humanizePubKey(wallet), publicKey: wallet);
},
);
}
......
......@@ -9,7 +9,9 @@ import '../connectivity_widget_wrapper_wrapper.dart';
import 'card_text_style.dart';
class CardNameEditable extends StatefulWidget {
const CardNameEditable({super.key});
const CardNameEditable({super.key, required this.defValue});
final String defValue;
@override
State<CardNameEditable> createState() => _CardNameEditableState();
......@@ -19,16 +21,17 @@ class _CardNameEditableState extends State<CardNameEditable> {
bool _isEditingText = false;
final TextEditingController _controller = TextEditingController();
late String currentText;
final String defValue = tr('your_name_here');
final String pubKey = SharedPreferencesHelper().getPubKey();
final bool isG1nkgoCard = SharedPreferencesHelper().isG1nkgoCard();
String _previousValue = '';
bool _isSubmitting = false;
@override
void initState() {
final String localUsername = SharedPreferencesHelper().getName();
currentText = localUsername.isEmpty ? defValue : localUsername;
currentText = localUsername.isEmpty ? widget.defValue : localUsername;
super.initState();
}
......@@ -48,7 +51,7 @@ class _CardNameEditableState extends State<CardNameEditable> {
SharedPreferencesHelper().setName(name: name);
} else {
_controller.text = '';
currentText = defValue;
currentText = widget.defValue;
SharedPreferencesHelper().setName(name: '');
}
}
......@@ -85,78 +88,82 @@ class _CardNameEditableState extends State<CardNameEditable> {
future: _initValue(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
const Color black = Colors.black87;
return _isEditingText
? SizedBox(
width: 150.0,
child: SizedBox(
height: 40.0,
child: TextField(
// focusNode: myFocusNode,
style: const TextStyle(color: black),
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 5.0, horizontal: 7.0),
filled: true,
fillColor: Colors.white,
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
width: 150.0,
child: SizedBox(
height: 40.0,
child: TextField(
// focusNode: myFocusNode,
style: const TextStyle(color: black),
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 5.0, horizontal: 7.0),
filled: true,
fillColor: Colors.white,
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(width: 2.0),
),
suffix: const Text('$userNameSuffix '),
suffixIcon: _isSubmitting
? const RefreshProgressIndicator()
: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
_isEditingText = false;
});
},
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child: Icon(Icons.cancel_outlined,
color: black),
),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(width: 2.0),
GestureDetector(
onTap: () {
_updateValue(_controller.text);
},
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child: Icon(Icons.check, color: black),
),
),
suffix: const Text('$userNameSuffix '),
suffixIcon: _isSubmitting
? const RefreshProgressIndicator()
: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
_isEditingText = false;
});
},
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child: Icon(Icons.cancel_outlined,
color: black),
),
),
GestureDetector(
onTap: () {
_updateValue(_controller.text);
},
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child: Icon(Icons.check, color: black),
),
),
],
),
),
cursorColor: black,
onSubmitted: _updateValue,
enabled: !_isSubmitting,
/* onChanged: (String value) {
],
),
),
cursorColor: black,
onSubmitted: _updateValue,
enabled: !_isSubmitting,
/* onChanged: (String value) {
if (value.isEmpty) {
_deleteValue();
}
}, */
/*onSubmitted: (String newValue) {
/*onSubmitted: (String newValue) {
updateName(newValue);
}, */
// maxLength: 15,
autofocus: true,
controller: _controller,
)))
// maxLength: 15,
autofocus: true,
controller: _controller,
)))
: Tooltip(
message: tr('your_name_here'),
child: CardNameText(
currentText: currentText,
isGinkgoCard: SharedPreferencesHelper().isG1nkgoCard(),
onTap: () => setState(() {
_isEditingText = true;
})));
message: widget.defValue,
child: CardNameText(
currentText: currentText,
isGinkgoCard: isG1nkgoCard,
onTap: () =>
isG1nkgoCard
? setState(() {
_isEditingText = true;
})
: null));
});
}
......@@ -178,13 +185,14 @@ class _CardNameEditableState extends State<CardNameEditable> {
} else {
setState(() {
_controller.text = _previousValue;
currentText = _previousValue.isEmpty ? defValue : _previousValue;
currentText =
_previousValue.isEmpty ? widget.defValue : _previousValue;
});
}
} catch (e) {
setState(() {
_controller.text = _previousValue;
currentText = _previousValue.isEmpty ? defValue : _previousValue;
currentText = _previousValue.isEmpty ? widget.defValue : _previousValue;
});
}
setState(() {
......@@ -204,12 +212,12 @@ class _CardNameEditableState extends State<CardNameEditable> {
SharedPreferencesHelper().setName(name: '');
setState(() {
_controller.text = '';
currentText = defValue;
currentText = widget.defValue;
});
} catch (e) {
setState(() {
_controller.text = _previousValue;
currentText = _previousValue.isEmpty ? defValue : _previousValue;
currentText = _previousValue.isEmpty ? widget.defValue : _previousValue;
});
}
setState(() {
......@@ -229,28 +237,29 @@ class _CardNameEditableState extends State<CardNameEditable> {
}
class CardNameText extends StatelessWidget {
CardNameText(
{super.key,
required this.currentText,
required this.onTap,
required this.isGinkgoCard});
const CardNameText({super.key,
required this.currentText,
required this.onTap,
required this.isGinkgoCard});
final String currentText;
final bool isGinkgoCard;
// Dup above
final String defValue = tr('your_name_here');
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
// Dup above
final String defValue = isGinkgoCard ? tr('your_name_here') : '';
return InkWell(
child: RichText(
// softWrap: true,
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
style: DefaultTextStyle
.of(context)
.style,
children: <TextSpan>[
if (currentText == defValue)
TextSpan(
......
......@@ -93,7 +93,12 @@ class CreditCard extends StatelessWidget {
'assets/img/chip.svg',
)),
const SizedBox(width: 10.0),
const Expanded(child: CardNameEditable())
Expanded(
child: CardNameEditable(
defValue: SharedPreferencesHelper().isG1nkgoCard()
? tr('your_name_here')
: '',
)),
])),
const SizedBox(height: 6.0),
Padding(
......
......@@ -8,10 +8,12 @@ import '../../../data/models/payment_state.dart';
import '../../../data/models/theme_cubit.dart';
import '../../../data/models/transaction_cubit.dart';
import '../../../g1/currency.dart';
import '../../../shared_prefs_helper.dart';
import '../../logger.dart';
import '../../pay_helper.dart';
import '../../tutorial_keys.dart';
import '../../ui_helpers.dart';
import '../fifth_screen/import_dialog.dart';
import '../form_error_widget.dart';
import 'g1_textfield.dart';
......@@ -37,7 +39,7 @@ class _PayFormState extends State<PayForm> {
}
@override
Widget build(BuildContext context) {
Widget build(BuildContext cp) {
return BlocBuilder<PaymentCubit, PaymentState>(
builder: (BuildContext context, PaymentState state) {
final AppCubit appCubit = context.watch<AppCubit>();
......@@ -106,8 +108,28 @@ class _PayFormState extends State<PayForm> {
Icons.send,
color: sentColor,
),
onPressed:
_onPressed(state, context, currency, currentUd),
onPressed: () async {
bool hasPass = false;
if (!SharedPreferencesHelper().isG1nkgoCard() &&
!SharedPreferencesHelper().hasVolatile()) {
hasPass = await showImportCesiumWalletDialog(
context,
SharedPreferencesHelper().getPubKey()) ??
false;
} else {
hasPass = true;
}
if (hasPass) {
if (mounted) {
final Future<void> Function()? func =
_onPressed(
state, context, currency, currentUd);
if (func != null) {
func();
}
}
}
},
splashRadius: 20,
splashColor: Colors.white.withOpacity(0.5),
highlightColor: Colors.transparent,
......@@ -199,7 +221,7 @@ class _PayFormState extends State<PayForm> {
}
double getBalance(BuildContext context) =>
context.watch<TransactionCubit>().balance;
context.read<TransactionCubit>().balance;
}
class RetryException implements Exception {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment