forked from alexvasl/drifter_app
Added QRCode screen, in the development of the profile screen
This commit is contained in:
parent
a7ea864c47
commit
c7d0a114e0
BIN
assets/images/avatar.png
Normal file
BIN
assets/images/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
assets/images/banner.png
Normal file
BIN
assets/images/banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
BIN
assets/images/logo/drifter_logo_white.png
Normal file
BIN
assets/images/logo/drifter_logo_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
BIN
assets/images/qr.png
Normal file
BIN
assets/images/qr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 462 B |
@ -4,6 +4,7 @@ import 'package:drifter/pages/create_account_screen/create_account_screen.dart';
|
|||||||
import 'package:drifter/pages/home_screen/home_screen_widget.dart';
|
import 'package:drifter/pages/home_screen/home_screen_widget.dart';
|
||||||
import 'package:drifter/pages/login_screen/login_screen.dart';
|
import 'package:drifter/pages/login_screen/login_screen.dart';
|
||||||
import 'package:drifter/pages/main_screen/main_screen_widget.dart';
|
import 'package:drifter/pages/main_screen/main_screen_widget.dart';
|
||||||
|
import 'package:drifter/pages/qr_code_screen/qr_code_screen.dart';
|
||||||
import 'package:drifter/pages/settings_screen/settings_screen.dart';
|
import 'package:drifter/pages/settings_screen/settings_screen.dart';
|
||||||
import 'package:drifter/pages/splash_screen/splash_screen.dart';
|
import 'package:drifter/pages/splash_screen/splash_screen.dart';
|
||||||
import 'package:drifter/pages/terms_of_service/terms_of_service.dart';
|
import 'package:drifter/pages/terms_of_service/terms_of_service.dart';
|
||||||
@ -42,6 +43,7 @@ class MyApp extends StatelessWidget {
|
|||||||
'/createAccount': (context) => const CreateAccountScreen(),
|
'/createAccount': (context) => const CreateAccountScreen(),
|
||||||
'/MainScreen': (context) => const MainScreenWidget(),
|
'/MainScreen': (context) => const MainScreenWidget(),
|
||||||
'/Settings': (context) => const SettingsScreen(),
|
'/Settings': (context) => const SettingsScreen(),
|
||||||
|
'/QrCodeScreen': (context) => const QrCodeScreen(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import 'package:drifter/pages/home_screen/widgets/message_text_button_widget.dar
|
|||||||
import 'package:drifter/pages/home_screen/widgets/message_text_form_field_widget.dart';
|
import 'package:drifter/pages/home_screen/widgets/message_text_form_field_widget.dart';
|
||||||
import 'package:drifter/pages/profile_screen/widgets/message_snack_bar.dart';
|
import 'package:drifter/pages/profile_screen/widgets/message_snack_bar.dart';
|
||||||
import 'package:nostr_tools/nostr_tools.dart';
|
import 'package:nostr_tools/nostr_tools.dart';
|
||||||
|
import 'package:toggle_switch/toggle_switch.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
const HomeScreen({super.key});
|
const HomeScreen({super.key});
|
||||||
@ -20,6 +21,7 @@ class HomeScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _HomeScreenState extends State<HomeScreen> {
|
class _HomeScreenState extends State<HomeScreen> {
|
||||||
bool _isConnected = false;
|
bool _isConnected = false;
|
||||||
|
List<bool> isSelected = [true, false];
|
||||||
|
|
||||||
final List<Event> _events = [];
|
final List<Event> _events = [];
|
||||||
final Map<String, Metadata> _metaDatas = {};
|
final Map<String, Metadata> _metaDatas = {};
|
||||||
@ -95,43 +97,123 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await _resubscribeStream();
|
await _resubscribeStream();
|
||||||
},
|
},
|
||||||
child: StreamBuilder(
|
child: Column(
|
||||||
stream: _controller.stream,
|
children: [
|
||||||
builder: (context, snapshot) {
|
// ToggleButtons(
|
||||||
// Inside the builder callback, the snapshot object contains the most recent event from the thread.
|
// isSelected: isSelected,
|
||||||
// If snapshot.hasData is true, there is data to display. In this case, ListView.builder is returned, which displays a list of NoostCard widgets.
|
// renderBorder: false,
|
||||||
if (snapshot.hasData) {
|
// fillColor: Color(0xFFFFFFFF),
|
||||||
return ListView.builder(
|
// selectedColor: Color(0xFF4F46F1),
|
||||||
// The itemCount property of ListView.builder is set to _events.length, , which is the number of events in the _events list.
|
// disabledColor: Color(0xFF837CA3),
|
||||||
itemCount: _events.length,
|
// children: <Widget>[
|
||||||
itemBuilder: (context, index) {
|
// Container(
|
||||||
final event = _events[index];
|
// margin: const EdgeInsets.all(4),
|
||||||
final metadata = _metaDatas[event.pubkey];
|
// child: const Text('Following')),
|
||||||
// For each event, a Noost object is created that encapsulates the details of the event, including id, avatarUrl, name,username, time, content и pubkey.
|
// Container(
|
||||||
// _metaDatas, you can map the event public key to the author's metadata.
|
// margin: const EdgeInsets.all(4),
|
||||||
final domain = Domain(
|
// child: const Text('Global')),
|
||||||
noteId: event.id,
|
// ],
|
||||||
avatarUrl: metadata?.picture ??
|
// onPressed: (int newIndex) {
|
||||||
'https://robohash.org/${event.pubkey}',
|
// setState(() {
|
||||||
name: metadata?.name ?? 'Anon',
|
// for (int index = 0; index < isSelected.length; index++) {
|
||||||
username: metadata?.displayName ??
|
// if (index == newIndex) {
|
||||||
(metadata?.display_name ?? 'Anon'),
|
// isSelected[index] = true;
|
||||||
time: TimeAgo.format(event.created_at),
|
// } else {
|
||||||
content: event.content,
|
// isSelected[index] = false;
|
||||||
pubkey: event.pubkey,
|
// }
|
||||||
);
|
// }
|
||||||
return DomainCard(domain: domain);
|
// });
|
||||||
|
// }),
|
||||||
|
ToggleSwitch(
|
||||||
|
minWidth: double.infinity,
|
||||||
|
minHeight: 40,
|
||||||
|
totalSwitches: 2,
|
||||||
|
labels: ['Following', 'Global'],
|
||||||
|
activeBgColor: [AppColors.toggleSwitchActiveBg],
|
||||||
|
activeFgColor: AppColors.toggleSwitchTextActive,
|
||||||
|
inactiveBgColor: AppColors.toggleSwitchBg,
|
||||||
|
inactiveFgColor: AppColors.toggleSwitchTextInactive,
|
||||||
|
activeBorders: [
|
||||||
|
Border.all(
|
||||||
|
color: AppColors.toggleSwitchBg,
|
||||||
|
width: 4,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
radiusStyle: true,
|
||||||
|
cornerRadius: 100,
|
||||||
|
customTextStyles: [
|
||||||
|
TextStyle(fontSize: 14, fontWeight: FontWeight.w600)
|
||||||
|
],
|
||||||
|
onToggle: (indexToggle) {
|
||||||
|
print(indexToggle);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: StreamBuilder(
|
||||||
|
stream: _controller.stream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
// Inside the builder callback, the snapshot object contains the most recent event from the thread.
|
||||||
|
// If snapshot.hasData is true, there is data to display. In this case, ListView.builder is returned, which displays a list of NoostCard widgets.
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
return ListView.builder(
|
||||||
|
// The itemCount property of ListView.builder is set to _events.length, , which is the number of events in the _events list.
|
||||||
|
itemCount: _events.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final event = _events[index];
|
||||||
|
final metadata = _metaDatas[event.pubkey];
|
||||||
|
// For each event, a Noost object is created that encapsulates the details of the event, including id, avatarUrl, name,username, time, content и pubkey.
|
||||||
|
// _metaDatas, you can map the event public key to the author's metadata.
|
||||||
|
final domain = Domain(
|
||||||
|
noteId: event.id,
|
||||||
|
avatarUrl: metadata?.picture ??
|
||||||
|
'https://robohash.org/${event.pubkey}',
|
||||||
|
name: metadata?.name ?? 'Anon',
|
||||||
|
username: metadata?.displayName ??
|
||||||
|
(metadata?.display_name ?? 'Anon'),
|
||||||
|
time: TimeAgo.format(event.created_at),
|
||||||
|
content: event.content,
|
||||||
|
pubkey: event.pubkey,
|
||||||
|
);
|
||||||
|
return DomainCard(domain: domain);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else if (snapshot.connectionState ==
|
||||||
|
ConnectionState.waiting) {
|
||||||
|
return const Center(child: Text('Loading....'));
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Center(child: Text('Error: ${snapshot.error}'));
|
||||||
|
}
|
||||||
|
return const CenteredCircularProgressIndicator();
|
||||||
},
|
},
|
||||||
);
|
),
|
||||||
} else if (snapshot.connectionState == ConnectionState.waiting) {
|
),
|
||||||
return const Center(child: Text('Loading....'));
|
],
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
|
||||||
}
|
|
||||||
return const CenteredCircularProgressIndicator();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// ToggleButtons(
|
||||||
|
// isSelected: isSelected,
|
||||||
|
// children: <Widget>[
|
||||||
|
// SizedBox(width: 300, child: Text('Following')),
|
||||||
|
// SizedBox(child: Text('Global')),
|
||||||
|
// ],
|
||||||
|
// onPressed: (int newIndex) {
|
||||||
|
// setState(() {
|
||||||
|
// for (int index = 0;
|
||||||
|
// index < isSelected.length;
|
||||||
|
// index++) {
|
||||||
|
// if (index == newIndex) {
|
||||||
|
// isSelected[index] = true;
|
||||||
|
// } else {
|
||||||
|
// isSelected[index] = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }),
|
||||||
|
|
||||||
floatingActionButton: Keys.keysExist
|
floatingActionButton: Keys.keysExist
|
||||||
? CreatePost(
|
? CreatePost(
|
||||||
// The publishNote function is called when the user launches the "Noost!" button in the dialog box.
|
// The publishNote function is called when the user launches the "Noost!" button in the dialog box.
|
||||||
@ -318,12 +400,15 @@ class DomainCard extends StatelessWidget {
|
|||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: FadeInImage(
|
child: ClipRRect(
|
||||||
placeholder: const NetworkImage(
|
borderRadius: BorderRadius.circular(8),
|
||||||
'https://media.tenor.com/On7kvXhzml4AAAAj/loading-gif.gif',
|
child: FadeInImage(
|
||||||
|
placeholder: const NetworkImage(
|
||||||
|
'https://media.tenor.com/On7kvXhzml4AAAAj/loading-gif.gif',
|
||||||
|
),
|
||||||
|
image: NetworkImage(imageLinks.first),
|
||||||
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
image: NetworkImage(imageLinks.first),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -132,94 +132,390 @@ class ProfileScreenState extends State<ProfileScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
privateKeyInput.text = _toHex ? Keys.nsecKey : Keys.privateKey;
|
publicKeyInput.text = Keys.npubKey;
|
||||||
publicKeyInput.text = _toHex ? Keys.npubKey : Keys.publicKey;
|
|
||||||
|
|
||||||
return ListView(
|
return Container(
|
||||||
children: [
|
color: AppColors.profileWrapperBg,
|
||||||
const SizedBox(
|
child: Column(
|
||||||
height: 60,
|
children: [
|
||||||
),
|
Stack(
|
||||||
const UserInfo(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 40,
|
|
||||||
),
|
|
||||||
FormKeys(),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
children: [
|
||||||
Keys.keysExist
|
Container(
|
||||||
? IconButton(
|
width: double.infinity,
|
||||||
onPressed: () {
|
height: 70,
|
||||||
setState(() {
|
child: FittedBox(
|
||||||
_toHex = !_toHex;
|
child: Image.asset('assets/images/banner.png'),
|
||||||
});
|
fit: BoxFit.fill,
|
||||||
},
|
),
|
||||||
icon: const Icon(Icons.refresh))
|
),
|
||||||
// ElevatedButton(
|
Row(
|
||||||
// style: ButtonStyle(
|
children: [
|
||||||
// backgroundColor:
|
Padding(
|
||||||
// MaterialStateProperty.all(AppColors.background)),
|
padding:
|
||||||
// onPressed: () {
|
const EdgeInsets.only(top: 30, left: 16, right: 58),
|
||||||
// keysExistDialog(
|
child: ClipRRect(
|
||||||
// Nostr.instance.keysService
|
borderRadius: BorderRadius.circular(200),
|
||||||
// .encodePublicKeyToNpub(Keys.publicKey),
|
child: Container(
|
||||||
// Nostr.instance.keysService
|
width: 80,
|
||||||
// .encodePrivateKeyToNsec(Keys.privateKey),
|
height: 80,
|
||||||
// );
|
decoration: BoxDecoration(
|
||||||
// },
|
border: Border.all(
|
||||||
// child: const Text(
|
width: 2, color: Color(0xFFF2EFFF))),
|
||||||
// 'Keys',
|
child: Image.asset('assets/images/avatar.png')),
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
: Row(
|
|
||||||
children: [
|
|
||||||
ElevatedButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor: MaterialStateProperty.all(
|
|
||||||
AppColors.background)),
|
|
||||||
onPressed: () {
|
|
||||||
modalBottomSheet();
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
'Generate Keys',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 100),
|
|
||||||
ElevatedButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor: MaterialStateProperty.all(
|
|
||||||
AppColors.background)),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pushNamed(context, '/login').then((_) {
|
|
||||||
initState();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
'Login',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
Keys.keysExist
|
),
|
||||||
? Row(
|
Expanded(
|
||||||
children: [
|
child: Container(
|
||||||
IconButton(
|
margin: EdgeInsets.only(top: 74, right: 16),
|
||||||
onPressed: () {
|
child: Row(
|
||||||
deleteKeysDialog();
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
},
|
children: [
|
||||||
icon: const Icon(Icons.delete)),
|
SizedBox(
|
||||||
],
|
width: 32,
|
||||||
)
|
height: 32,
|
||||||
: Container(),
|
child: FloatingActionButton(
|
||||||
|
backgroundColor:
|
||||||
|
AppColors.buttonSecondaryDefaultBg,
|
||||||
|
onPressed: () {},
|
||||||
|
elevation: 0,
|
||||||
|
child: Icon(
|
||||||
|
Icons.edit,
|
||||||
|
size: 18,
|
||||||
|
color: AppColors.buttonSecondaryIcon,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
child: FloatingActionButton(
|
||||||
|
backgroundColor:
|
||||||
|
AppColors.buttonSecondaryDefaultBg,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pushNamed(context, '/QrCodeScreen');
|
||||||
|
},
|
||||||
|
elevation: 0,
|
||||||
|
child: Icon(
|
||||||
|
Icons.qr_code,
|
||||||
|
size: 18,
|
||||||
|
color: AppColors.buttonSecondaryIcon,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
child: FloatingActionButton(
|
||||||
|
backgroundColor:
|
||||||
|
AppColors.buttonSecondaryDefaultBg,
|
||||||
|
onPressed: () {},
|
||||||
|
elevation: 0,
|
||||||
|
child: Icon(
|
||||||
|
Icons.mail_outlined,
|
||||||
|
size: 18,
|
||||||
|
color: AppColors.buttonSecondaryIcon,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 100,
|
||||||
|
height: 32,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text(
|
||||||
|
'Follow',
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
AppColors.buttonPrimaryDefaultText),
|
||||||
|
),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
AppColors.buttonPrimaryDefaultBg,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(100)))),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
Container(
|
||||||
],
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Cameron Williamson',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileFullName,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
Text('@cameron',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileUserName,
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'This is the description of my profile. I am a nostrich and I love cats. Follow me for fun pictures and bad jokes. I also want to be a politician.',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSummary,
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: TextField(
|
||||||
|
style: TextStyle(color: AppColors.profileKeyText),
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
suffixIcon: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.copy),
|
||||||
|
color: AppColors.buttonSecondaryIcon,
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.qr_code),
|
||||||
|
color: AppColors.buttonSecondaryIcon,
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: AppColors.profileKeyField,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide:
|
||||||
|
BorderSide(width: 0, style: BorderStyle.none),
|
||||||
|
)),
|
||||||
|
minLines: 2,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: publicKeyInput,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'nip-05-name',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'www.cameronforpresident.com',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.score,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'@cameron_official',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'cameron.williamson.com/@cameron_official',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.flash_on,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'whoknowswhatgoeshere',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
TextButton.icon(
|
||||||
|
// <-- TextButton
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.flash_on,
|
||||||
|
size: 15.0,
|
||||||
|
color: AppColors.profileSocialIcons,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
'cameron@satoshiwallet.com',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.profileSocialLinks,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
// return ListView(
|
||||||
|
// children: [
|
||||||
|
// const SizedBox(
|
||||||
|
// height: 60,
|
||||||
|
// ),
|
||||||
|
// const UserInfo(),
|
||||||
|
// const SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
// ),
|
||||||
|
// FormKeys(),
|
||||||
|
// const SizedBox(height: 20),
|
||||||
|
// Padding(
|
||||||
|
// padding: const EdgeInsets.all(16.0),
|
||||||
|
// child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
// children: [
|
||||||
|
// Keys.keysExist
|
||||||
|
// ? IconButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// setState(() {
|
||||||
|
// _toHex = !_toHex;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// icon: const Icon(Icons.refresh))
|
||||||
|
// // ElevatedButton(
|
||||||
|
// // style: ButtonStyle(
|
||||||
|
// // backgroundColor:
|
||||||
|
// // MaterialStateProperty.all(AppColors.background)),
|
||||||
|
// // onPressed: () {
|
||||||
|
// // keysExistDialog(
|
||||||
|
// // Nostr.instance.keysService
|
||||||
|
// // .encodePublicKeyToNpub(Keys.publicKey),
|
||||||
|
// // Nostr.instance.keysService
|
||||||
|
// // .encodePrivateKeyToNsec(Keys.privateKey),
|
||||||
|
// // );
|
||||||
|
// // },
|
||||||
|
// // child: const Text(
|
||||||
|
// // 'Keys',
|
||||||
|
// // ),
|
||||||
|
// // )
|
||||||
|
// : Row(
|
||||||
|
// children: [
|
||||||
|
// ElevatedButton(
|
||||||
|
// style: ButtonStyle(
|
||||||
|
// backgroundColor: MaterialStateProperty.all(
|
||||||
|
// AppColors.background)),
|
||||||
|
// onPressed: () {
|
||||||
|
// modalBottomSheet();
|
||||||
|
// },
|
||||||
|
// child: const Text(
|
||||||
|
// 'Generate Keys',
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// SizedBox(width: 100),
|
||||||
|
// ElevatedButton(
|
||||||
|
// style: ButtonStyle(
|
||||||
|
// backgroundColor: MaterialStateProperty.all(
|
||||||
|
// AppColors.background)),
|
||||||
|
// onPressed: () {
|
||||||
|
// Navigator.pushNamed(context, '/login').then((_) {
|
||||||
|
// initState();
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// child: const Text(
|
||||||
|
// 'Login',
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// Keys.keysExist
|
||||||
|
// ? Row(
|
||||||
|
// children: [
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// deleteKeysDialog();
|
||||||
|
// },
|
||||||
|
// icon: const Icon(Icons.delete)),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
// : Container(),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
Form FormKeys() {
|
Form FormKeys() {
|
||||||
|
166
lib/pages/qr_code_screen/qr_code_screen.dart
Normal file
166
lib/pages/qr_code_screen/qr_code_screen.dart
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import 'package:drifter/models/models.dart';
|
||||||
|
import 'package:drifter/pages/terms_of_service/btn_continue_terms_of_service.dart';
|
||||||
|
import 'package:drifter/pages/terms_of_service/terms_of_service_text.dart';
|
||||||
|
import 'package:drifter/theme/app_colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter/src/widgets/placeholder.dart';
|
||||||
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
|
|
||||||
|
class QrCodeScreen extends StatefulWidget {
|
||||||
|
const QrCodeScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<QrCodeScreen> createState() => _QrCodeScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _QrCodeScreenState extends State<QrCodeScreen> {
|
||||||
|
String _publicKey = Keys.npubKey;
|
||||||
|
bool isCopied = false;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.arrow_back,
|
||||||
|
color: AppColors.topNavIconBack,
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: AppColors.mainBackground,
|
||||||
|
),
|
||||||
|
backgroundColor: AppColors.mainBackground,
|
||||||
|
body: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 10, right: 16, left: 16, bottom: 16),
|
||||||
|
child: Center(
|
||||||
|
child: Column(children: [
|
||||||
|
Text(
|
||||||
|
'Follow me on Nostr',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF302F38),
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 24, bottom: 83, right: 48, left: 48),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
height: 406,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 32.0, bottom: 10),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(200),
|
||||||
|
child: Container(
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
width: 2, color: Color(0xFFF2EFFF))),
|
||||||
|
child: Image.asset('assets/images/avatar.png')),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Cameron Williams on',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF302F38),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'@cameron',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12, color: AppColors.profileUserName),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Container(
|
||||||
|
width: 230,
|
||||||
|
child: Text(_publicKey,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.profileSocialLinks))),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Container(
|
||||||
|
width: 143,
|
||||||
|
height: 143,
|
||||||
|
child: QrImageView(
|
||||||
|
eyeStyle: QrEyeStyle(
|
||||||
|
color: AppColors.qrCodeBody,
|
||||||
|
eyeShape: QrEyeShape.square),
|
||||||
|
dataModuleStyle:
|
||||||
|
QrDataModuleStyle(color: AppColors.qrCodeBody),
|
||||||
|
embeddedImage: AssetImage(
|
||||||
|
'assets/images/logo/drifter_logo_white.png'),
|
||||||
|
data: _publicKey,
|
||||||
|
version: QrVersions.auto,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Expanded(child: SizedBox()),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 56,
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100)),
|
||||||
|
backgroundColor: AppColors.buttonSecondaryDefaultBg),
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: _publicKey))
|
||||||
|
.then((value) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||||
|
content: Text('Copied to clipboard'),
|
||||||
|
));
|
||||||
|
isCopied = true;
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: isCopied
|
||||||
|
? Text(
|
||||||
|
'Copied',
|
||||||
|
style: TextStyle(color: AppColors.buttonSecondaryText),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
'Copy user ID',
|
||||||
|
style: TextStyle(color: AppColors.buttonSecondaryText),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 56,
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100)),
|
||||||
|
backgroundColor: AppColors.buttonPrimaryDefaultBg),
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text(
|
||||||
|
'Share QR code',
|
||||||
|
style: TextStyle(color: AppColors.buttonPrimaryDefaultText),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ abstract class AppColors {
|
|||||||
static const background = Color(0xFF4f46f1);
|
static const background = Color(0xFF4f46f1);
|
||||||
static const mainAccent = Color(0xFFFFCC11);
|
static const mainAccent = Color(0xFFFFCC11);
|
||||||
static const mainBackground = Color(0xFFF2EFFF);
|
static const mainBackground = Color(0xFFF2EFFF);
|
||||||
|
|
||||||
|
// Button
|
||||||
static const buttonPrimaryDefaultBg = Color(0xFF4F46F1);
|
static const buttonPrimaryDefaultBg = Color(0xFF4F46F1);
|
||||||
static const buttonPrimaryDefaultText = Color(0xFFFFFFFF);
|
static const buttonPrimaryDefaultText = Color(0xFFFFFFFF);
|
||||||
static const buttonPrimaryDisabledBg = Color(0x1A18171B);
|
static const buttonPrimaryDisabledBg = Color(0x1A18171B);
|
||||||
@ -11,6 +13,9 @@ abstract class AppColors {
|
|||||||
static const buttonOutlinedDefaultBorder = Color(0xFF4F46F1);
|
static const buttonOutlinedDefaultBorder = Color(0xFF4F46F1);
|
||||||
static const buttonOutlinedDefaultText = Color(0xFF4F46F1);
|
static const buttonOutlinedDefaultText = Color(0xFF4F46F1);
|
||||||
static const buttonOutlinedPressedBg = Color(0xFFE3E0F9);
|
static const buttonOutlinedPressedBg = Color(0xFFE3E0F9);
|
||||||
|
static const buttonSecondaryDefaultBg = Color(0xFFDCDAFC);
|
||||||
|
static const buttonSecondaryIcon = Color(0xFF2D25BC);
|
||||||
|
static const buttonSecondaryText = Color(0xFF2D25BC);
|
||||||
|
|
||||||
// TopNav
|
// TopNav
|
||||||
|
|
||||||
@ -72,4 +77,18 @@ abstract class AppColors {
|
|||||||
static const postActionIconDefault = Color(0xFFC8C5D0);
|
static const postActionIconDefault = Color(0xFFC8C5D0);
|
||||||
static const postActionIconPressed = Color(0xFFFE82B1);
|
static const postActionIconPressed = Color(0xFFFE82B1);
|
||||||
static const postBookmark = Color(0xFF8482FF);
|
static const postBookmark = Color(0xFF8482FF);
|
||||||
|
|
||||||
|
// Profile
|
||||||
|
|
||||||
|
static const profileWrapperBg = Color(0xFFF9F8FF);
|
||||||
|
static const profileFullName = Color(0xFF302F38);
|
||||||
|
static const profileUserName = Color(0xFF787680);
|
||||||
|
static const profileSummary = Color(0xFF302F38);
|
||||||
|
static const profileKeyField = Color(0xFFF2EFFF);
|
||||||
|
static const profileKeyText = Color(0xFF6E61A0);
|
||||||
|
static const profileSocialLinks = Color(0xFF4F46F1);
|
||||||
|
static const profileSocialIcons = Color(0xFF837CA3);
|
||||||
|
|
||||||
|
// QR code
|
||||||
|
static const qrCodeBody = Color(0xFF25207A);
|
||||||
}
|
}
|
||||||
|
18
pubspec.lock
18
pubspec.lock
@ -352,6 +352,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.3"
|
version: "3.7.3"
|
||||||
|
qr:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: qr
|
||||||
|
sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
qr_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: qr_flutter
|
||||||
|
sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -479,4 +495,4 @@ packages:
|
|||||||
version: "6.2.2"
|
version: "6.2.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.19.6 <3.0.0"
|
dart: ">=2.19.6 <3.0.0"
|
||||||
flutter: ">=3.7.0-0"
|
flutter: ">=3.7.0"
|
||||||
|
@ -40,6 +40,7 @@ dependencies:
|
|||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
another_flushbar: ^1.12.29
|
another_flushbar: ^1.12.29
|
||||||
|
qr_flutter: ^4.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -64,8 +65,9 @@ flutter:
|
|||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
assets:
|
||||||
- assets/images//icons/
|
- assets/images/
|
||||||
- assets/images//logo/
|
- assets/images/icons/
|
||||||
|
- assets/images/logo/
|
||||||
|
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user