main #2

Closed
ryleedavis wants to merge 8 commits from alexvasl/drifter_app:main into main
11 changed files with 710 additions and 124 deletions
Showing only changes of commit c7d0a114e0 - Show all commits

BIN
assets/images/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/images/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
assets/images/qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

View File

@ -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/login_screen/login_screen.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/splash_screen/splash_screen.dart';
import 'package:drifter/pages/terms_of_service/terms_of_service.dart';
@ -42,6 +43,7 @@ class MyApp extends StatelessWidget {
'/createAccount': (context) => const CreateAccountScreen(),
'/MainScreen': (context) => const MainScreenWidget(),
'/Settings': (context) => const SettingsScreen(),
'/QrCodeScreen': (context) => const QrCodeScreen(),
},
);
}

View File

@ -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/profile_screen/widgets/message_snack_bar.dart';
import 'package:nostr_tools/nostr_tools.dart';
import 'package:toggle_switch/toggle_switch.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@ -20,6 +21,7 @@ class HomeScreen extends StatefulWidget {
class _HomeScreenState extends State<HomeScreen> {
bool _isConnected = false;
List<bool> isSelected = [true, false];
final List<Event> _events = [];
final Map<String, Metadata> _metaDatas = {};
@ -95,6 +97,61 @@ class _HomeScreenState extends State<HomeScreen> {
onRefresh: () async {
await _resubscribeStream();
},
child: Column(
children: [
// ToggleButtons(
// isSelected: isSelected,
// renderBorder: false,
// fillColor: Color(0xFFFFFFFF),
// selectedColor: Color(0xFF4F46F1),
// disabledColor: Color(0xFF837CA3),
// children: <Widget>[
// Container(
// margin: const EdgeInsets.all(4),
// child: const Text('Following')),
// Container(
// margin: const EdgeInsets.all(4),
// child: const Text('Global')),
// ],
// onPressed: (int newIndex) {
// setState(() {
// for (int index = 0; index < isSelected.length; index++) {
// if (index == newIndex) {
// isSelected[index] = true;
// } else {
// isSelected[index] = false;
// }
// }
// });
// }),
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) {
@ -123,7 +180,8 @@ class _HomeScreenState extends State<HomeScreen> {
return DomainCard(domain: domain);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
} else if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(child: Text('Loading....'));
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
@ -132,6 +190,30 @@ class _HomeScreenState extends State<HomeScreen> {
},
),
),
],
),
),
// 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
? CreatePost(
// The publishNote function is called when the user launches the "Noost!" button in the dialog box.
@ -318,6 +400,8 @@ class DomainCard extends StatelessWidget {
color: Colors.transparent,
),
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: FadeInImage(
placeholder: const NetworkImage(
'https://media.tenor.com/On7kvXhzml4AAAAj/loading-gif.gif',
@ -326,6 +410,7 @@ class DomainCard extends StatelessWidget {
fit: BoxFit.cover,
),
),
),
],
),
),

View File

@ -132,94 +132,390 @@ class ProfileScreenState extends State<ProfileScreen> {
@override
Widget build(BuildContext context) {
privateKeyInput.text = _toHex ? Keys.nsecKey : Keys.privateKey;
publicKeyInput.text = _toHex ? Keys.npubKey : Keys.publicKey;
publicKeyInput.text = Keys.npubKey;
return ListView(
return Container(
color: AppColors.profileWrapperBg,
child: Column(
children: [
const SizedBox(
height: 60,
Stack(
children: [
Container(
width: double.infinity,
height: 70,
child: FittedBox(
child: Image.asset('assets/images/banner.png'),
fit: BoxFit.fill,
),
const UserInfo(),
const SizedBox(
height: 40,
),
FormKeys(),
const SizedBox(height: 20),
Row(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
padding:
const EdgeInsets.only(top: 30, left: 16, right: 58),
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')),
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(top: 74, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Keys.keysExist
? IconButton(
SizedBox(
width: 32,
height: 32,
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: () {
setState(() {
_toHex = !_toHex;
});
Navigator.pushNamed(context, '/QrCodeScreen');
},
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',
elevation: 0,
child: Icon(
Icons.qr_code,
size: 18,
color: AppColors.buttonSecondaryIcon,
),
),
SizedBox(width: 100),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
AppColors.background)),
onPressed: () {
Navigator.pushNamed(context, '/login').then((_) {
initState();
});
},
child: const Text(
'Login',
),
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)))),
)
],
),
Keys.keysExist
? Row(
),
)
],
)
],
),
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(
onPressed: () {
deleteKeysDialog();
},
icon: const Icon(Icons.delete)),
],
)
: Container(),
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() {

View 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),
),
),
),
]),
),
),
);
}
}

View File

@ -4,6 +4,8 @@ abstract class AppColors {
static const background = Color(0xFF4f46f1);
static const mainAccent = Color(0xFFFFCC11);
static const mainBackground = Color(0xFFF2EFFF);
// Button
static const buttonPrimaryDefaultBg = Color(0xFF4F46F1);
static const buttonPrimaryDefaultText = Color(0xFFFFFFFF);
static const buttonPrimaryDisabledBg = Color(0x1A18171B);
@ -11,6 +13,9 @@ abstract class AppColors {
static const buttonOutlinedDefaultBorder = Color(0xFF4F46F1);
static const buttonOutlinedDefaultText = Color(0xFF4F46F1);
static const buttonOutlinedPressedBg = Color(0xFFE3E0F9);
static const buttonSecondaryDefaultBg = Color(0xFFDCDAFC);
static const buttonSecondaryIcon = Color(0xFF2D25BC);
static const buttonSecondaryText = Color(0xFF2D25BC);
// TopNav
@ -72,4 +77,18 @@ abstract class AppColors {
static const postActionIconDefault = Color(0xFFC8C5D0);
static const postActionIconPressed = Color(0xFFFE82B1);
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);
}

View File

@ -352,6 +352,22 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description: flutter
@ -479,4 +495,4 @@ packages:
version: "6.2.2"
sdks:
dart: ">=2.19.6 <3.0.0"
flutter: ">=3.7.0-0"
flutter: ">=3.7.0"

View File

@ -40,6 +40,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
another_flushbar: ^1.12.29
qr_flutter: ^4.1.0
dev_dependencies:
flutter_test:
@ -64,8 +65,9 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
- assets/images//icons/
- assets/images//logo/
- assets/images/
- assets/images/icons/
- assets/images/logo/
# - images/a_dot_ham.jpeg