drifter_app/lib/pages/login_screen/login_screen.dart

253 lines
10 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:dart_nostr/dart_nostr.dart';
import 'package:drifter/models/models.dart';
import 'package:drifter/pages/home_screen/widgets/message_text_button_widget.dart';
import 'package:drifter/pages/profile_screen/profile_screen.dart';
import 'package:drifter/pages/profile_screen/widgets/keys_option_modal_bottom_sheet.dart';
import 'package:drifter/pages/profile_screen/widgets/message_snack_bar.dart';
import 'package:drifter/pages/profile_screen/widgets/ok_button_widget.dart';
import 'package:drifter/widgets/btn_continue.dart';
import 'package:drifter/theme/app_colors.dart';
import 'package:drifter/utilities/assets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_svg/svg.dart';
import 'package:nostr_tools/nostr_tools.dart';
import 'package:sliding_switch/sliding_switch.dart';
import 'package:toggle_switch/toggle_switch.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => LoginScreenState();
}
class LoginScreenState extends State<LoginScreen> {
final keyGenerator = KeyApi();
final nip19 = Nip19();
final indexToggle = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: AppColors.topNavIconBack,
),
onPressed: () => Navigator.of(context).pop(),
),
actions: <Widget>[
TextButton(
onPressed: () {},
child: Text('Skip'),
)
],
elevation: 0,
backgroundColor: AppColors.mainBackground,
),
backgroundColor: AppColors.mainBackground,
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const SizedBox(
height: 56,
),
ToggleSwitch(
minWidth: double.infinity,
minHeight: 56,
totalSwitches: 2,
labels: ['Login', 'View only'],
activeBgColor: [AppColors.toggleSwitchActiveBg],
activeFgColor: AppColors.toggleSwitchTextActive,
inactiveBgColor: AppColors.toggleSwitchBg,
inactiveFgColor: AppColors.toggleSwitchTextInactive,
activeBorders: [
Border.all(
color: AppColors.toggleSwitchBg,
width: 4,
),
],
radiusStyle: true,
cornerRadius: 8,
customTextStyles: [
TextStyle(fontSize: 14, fontWeight: FontWeight.w600)
],
onToggle: (indexToggle) {
print(indexToggle);
},
),
SizedBox(
height: 56,
),
const Text(
'Login',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
),
const SizedBox(height: 13),
const Text(
'Paste your password (AKA Private Key)',
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
const SizedBox(height: 24),
TextFormField(
decoration: InputDecoration(
filled: true,
fillColor: AppColors.textFieldDefaultBg,
labelText: 'nsec... / hex...',
labelStyle:
TextStyle(color: AppColors.textFieldDefaultText),
suffixIcon: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(Icons.paste),
color: AppColors.textFieldActiveIconTrail,
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.qr_code_scanner),
color: AppColors.textFieldActiveIconTrail,
onPressed: () {},
),
],
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
iconColor: AppColors.textFieldDefaultIconTrail),
controller: keyController,
key: formKey,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your private key';
}
try {
bool isValidHexKey =
Nostr.instance.keysService.isValidPrivateKey(value);
bool isValidNSec = value.trim().startsWith('nsec') &&
Nostr.instance.keysService.isValidPrivateKey(Nostr
.instance.keysService
.decodeNsecKeyToPrivateKey(value));
if (!(isValidHexKey || isValidNSec)) {
return 'Your private key is not valid.';
}
} on ChecksumVerificationException catch (e) {
return e.message;
} catch (e) {
return 'Error: $e';
}
return null;
}),
const SizedBox(height: 10),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
height: 168,
child: Note.note,
),
Expanded(child: SizedBox()),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
String privateKeyHex = keyController.text.trim();
String publicKeyHex;
String nsecKey;
String npubKey;
// if (privateKeyHex.startsWith('nsec')) {
// nsecKey = privateKeyHex;
// final decoded = Nostr.instance.keysService
// .decodeNsecKeyToPrivateKey(privateKeyHex);
// privateKeyHex = decoded;
// publicKeyHex = Nostr.instance.keysService
// .derivePublicKey(privateKey: 'privateKeyHex');
// npubKey = Nostr.instance.keysService
// .encodePublicKeyToNpub(publicKeyHex);
// } else {
// publicKeyHex = Nostr.instance.keysService
// .derivePublicKey(privateKey: 'privateKeyHex');
// nsecKey = Nostr.instance.keysService
// .encodePrivateKeyToNsec(privateKeyHex);
// npubKey = Nostr.instance.keysService
// .encodePublicKeyToNpub(publicKeyHex);
// }
if (privateKeyHex.startsWith('nsec')) {
final decoded = nip19.decode(privateKeyHex);
privateKeyHex = decoded['data'];
publicKeyHex = keyGenerator.getPublicKey(privateKeyHex);
nsecKey = nip19.nsecEncode(privateKeyHex);
npubKey = nip19.npubEncode(publicKeyHex);
} else {
publicKeyHex = keyGenerator.getPublicKey(privateKeyHex);
nsecKey = nip19.nsecEncode(privateKeyHex);
npubKey = nip19.npubEncode(publicKeyHex);
}
try {
ProfileScreenState().addKeyToStorage(
privateKeyHex, publicKeyHex, nsecKey, npubKey);
keyController.clear();
ScaffoldMessenger.of(context).showSnackBar(
MessageSnackBar(
label: 'Congratulations! Keys Stored!'),
);
Navigator.of(context).pop(true);
} catch (e) {}
} else {
formKey.currentState?.setState(() {});
}
},
child: Text(
'Continue',
style: TextStyle(fontSize: 16),
),
style: ButtonStyle(
shape: MaterialStatePropertyAll(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100))),
backgroundColor: const MaterialStatePropertyAll(
AppColors.buttonPrimaryDefaultBg),
foregroundColor: const MaterialStatePropertyAll(
AppColors.buttonPrimaryDefaultText)),
)),
],
),
),
);
}
}
abstract class Note {
static final note = Text.rich(
TextSpan(
style: TextStyle(
height: 1.6,
fontSize: 10,
fontWeight: FontWeight.w400,
),
children: <TextSpan>[
TextSpan(
style: TextStyle(color: AppColors.noteText),
text:
"Your private key starts with “nsec” or “hex” and gives your full access to your account. That means, if you log in using your private key, you will be able to make posts and send and receive private messages.\n\n"
"Your public key starts with “npub” and gives your view-only access to account. If you log in using your public key, you wont be able to make posts or access private messages, but you will be able to view your feed. Go to “View only” tab to log in via your public key.")
]),
);
}