From 0ee9aea4761acb11f2a1ccf069a48208f44f3810 Mon Sep 17 00:00:00 2001 From: Omar Toutounji Date: Wed, 25 Oct 2023 21:44:20 -0400 Subject: [PATCH] UI Redesign and added delete note feature --- README.md | 12 +- lib/routes/hwyd_routes.dart | 2 +- lib/screens/hwyd.dart | 8 +- lib/screens/journal_page.dart | 228 +++++++++++++++++++++++----------- test/hwyd_smoke_test.dart | 6 +- 5 files changed, 171 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 7ca6086..16ecd1d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ -# hwyd +The world's first nano journal. + Simple. + Focused. + Beautiful. + All you'll want to do is write your heart out. -A new Flutter project. + [![name](https://github.com/omartoutounji/hwyd/blob/master/assets/app%20store.svg)](https://apps.apple.com/ca/app/hwyd-privacy-first-journaling/id1557807577) + + [![name](https://github.com/omartoutounji/hwyd/blob/master/assets/google-play-badge.png)](https://play.google.com/store/apps/details?id=com.app.hwyd) + + [![name](https://github.com/omartoutounji/hwyd/blob/master/assets/hwyd_ipad_iphone.svg)](https://apps.apple.com/ca/app/hwyd-privacy-first-journaling/id1557807577) \ No newline at end of file diff --git a/lib/routes/hwyd_routes.dart b/lib/routes/hwyd_routes.dart index ca77468..67377da 100644 --- a/lib/routes/hwyd_routes.dart +++ b/lib/routes/hwyd_routes.dart @@ -2,5 +2,5 @@ import 'package:flutter/cupertino.dart'; import 'package:hwyd/screens/journal_page.dart'; Map routes = { - '/journal': (BuildContext context) => JournalPage(), + '/journal': (BuildContext context) => const JournalPage(), }; diff --git a/lib/screens/hwyd.dart b/lib/screens/hwyd.dart index e43c254..f4f0bb4 100644 --- a/lib/screens/hwyd.dart +++ b/lib/screens/hwyd.dart @@ -38,7 +38,7 @@ class _HwydState extends State { @override Widget build(BuildContext context) { - return showOnboard == true ? _buildIntroductionScreen() : JournalPage(); + return showOnboard == true ? _buildIntroductionScreen() : const JournalPage(); } Widget _buildIntroductionScreen() { @@ -55,7 +55,7 @@ class _HwydState extends State { PageViewModel( title: "Creating a new note", body: "Just tap the hwyd logo to create a new note️", - image: Center( + image: const Center( child: Icon( Icons.add, size: 250, @@ -66,7 +66,7 @@ class _HwydState extends State { title: "Viewing previous notes", body: "Swipe from left to right to see other notes. Don't worry about saving, everything auto-saves. Also don't worry about privacy, contents are only saved on your device so no one can access it but you. Not even hwyd.", - image: Center( + image: const Center( child: Icon(Icons.swipe, size: 250), ), ), @@ -74,7 +74,7 @@ class _HwydState extends State { title: "Changing font size", body: "Swipe the other way around from right to left and move the slider to change font size", - image: Center( + image: const Center( child: Icon(Icons.format_size, size: 250), ), ) diff --git a/lib/screens/journal_page.dart b/lib/screens/journal_page.dart index 9c75450..068ea96 100644 --- a/lib/screens/journal_page.dart +++ b/lib/screens/journal_page.dart @@ -9,6 +9,8 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../model/Note.dart'; class JournalPage extends StatefulWidget { + const JournalPage({super.key}); + @override _JournalPageState createState() => _JournalPageState(); } @@ -20,11 +22,15 @@ class _JournalPageState extends State { final Image logo = Image.asset('assets/hwyd_logo.png', width: 50); final textController = TextEditingController(); double _currentSliderValue = 80; + final GlobalKey _scaffoldKey = GlobalKey(); @override void initState() { super.initState(); _loadNotes(); + if (notes.isEmpty) { + _createNewNote(); + } greeting = getRandomGreeting(); } @@ -72,6 +78,18 @@ class _JournalPageState extends State { _save(); } + _deleteNote(index) async { + setState(() { + notes.removeAt(index); + if (notes.isEmpty) { + _createNewNote(); + } + currentNoteIndex = notes.length - 1; + textController.text = notes[currentNoteIndex].text; + }); + _save(); + } + TextStyle getStyle(double size) { return GoogleFonts.raleway( textStyle: TextStyle(fontWeight: FontWeight.w200, fontSize: size)); @@ -89,14 +107,14 @@ class _JournalPageState extends State { 'what\'s cracking?', 'life, huh?' ]; - final _random = new Random(); - return greetings[_random.nextInt(greetings.length)]; + final random = Random(); + return greetings[random.nextInt(greetings.length)]; } String getSliderLabel() { - if (_currentSliderValue == 20.0) + if (_currentSliderValue == 20.0) { return "S"; - else if (_currentSliderValue == 35.0) + } else if (_currentSliderValue == 35.0) return "M"; else if (_currentSliderValue == 50.0) return "L"; @@ -109,62 +127,103 @@ class _JournalPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + key: _scaffoldKey, body: SafeArea( child: Center( - child: Padding( - padding: const EdgeInsets.all(10), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - child: logo, - onTap: () { + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: IconButton( + onPressed: () => + _scaffoldKey.currentState!.openDrawer(), + icon: const Icon(Icons.menu)), + ), + Expanded( + child: Text( + notes[currentNoteIndex].name, + style: getStyle(30), + textAlign: TextAlign.center, + ), + ), + Expanded( + child: IconButton( + onPressed: () => + _scaffoldKey.currentState!.openEndDrawer(), + icon: const Icon(Icons.settings)), + ) + ], + ), + Expanded( + child: TextField( + keyboardType: TextInputType.text, + controller: textController, + maxLines: null, + decoration: InputDecoration( + border: InputBorder.none, + hintText: greeting, + hintStyle: getStyle(30), + ), + showCursor: true, + cursorColor: MediaQuery.of(context).platformBrightness == + Brightness.dark + ? Colors.white + : Colors.black, + style: getStyle(_currentSliderValue), + textAlign: TextAlign.center, + onChanged: notes.isNotEmpty + ? (text) { + List splittedString = text.split(" "); + if (splittedString.length > 1) { + setState(() { + notes[currentNoteIndex].name = + '${splittedString[0]} ${splittedString[1]}'; + notes[currentNoteIndex].text = text; + }); + } else { + setState(() { + notes[currentNoteIndex].text = text; + }); + } + _save(); + } + : null, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: ElevatedButton( + onPressed: () { _createNewNote(); }, - ) - ], - ), - Expanded( - child: TextField( - keyboardType: TextInputType.text, - controller: textController, - maxLines: null, - decoration: InputDecoration( - border: InputBorder.none, - hintText: greeting, - hintStyle: getStyle(30), + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + padding: const EdgeInsets.all(10), + backgroundColor: + MediaQuery.of(context).platformBrightness == + Brightness.dark + ? Colors.white + : Colors.black, + ), + child: Icon( + Icons.add, + size: 40, + color: MediaQuery.of(context).platformBrightness == + Brightness.dark + ? Colors.black + : Colors.white, + ), ), - showCursor: true, - cursorColor: MediaQuery.of(context).platformBrightness == - Brightness.dark - ? Colors.white - : Colors.black, - style: getStyle(_currentSliderValue), - textAlign: TextAlign.center, - onChanged: notes.length != 0 - ? (text) { - List splittedString = text.split(" "); - if (splittedString.length > 1) { - setState(() { - notes[currentNoteIndex].name = - splittedString[0] + ' ' + splittedString[1]; - notes[currentNoteIndex].text = text; - }); - } else { - setState(() { - notes[currentNoteIndex].text = text; - }); - } - _save(); - } - : null, ), - ) - ], - ), + ], + ), + ], ), ), ), @@ -183,44 +242,63 @@ class _JournalPageState extends State { // space to fit everything. child: ListView( // Important: Remove any padding from the ListView. - padding: EdgeInsets.only(top: 50), + padding: const EdgeInsets.only(top: 50), children: [ DrawerHeader( child: Text('Notes', style: GoogleFonts.raleway( textStyle: TextStyle( fontWeight: FontWeight.w400, - fontSize: 80, + fontSize: 60, color: MediaQuery.of(context).platformBrightness != Brightness.dark ? Colors.white : Colors.black))), ), SingleChildScrollView( - physics: ScrollPhysics(), + physics: const ScrollPhysics(), child: Column( children: [ ListView.builder( itemCount: notes.length, - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), scrollDirection: Axis.vertical, shrinkWrap: true, itemBuilder: (context, index) { - return ListTile( - tileColor: - currentNoteIndex == index ? Colors.grey : null, - title: Text(notes[index].name, - style: TextStyle( - fontSize: 30, - color: currentNoteIndex == index - ? null - : Colors.grey)), - onTap: () { - currentNoteIndex = index; - textController.text = - notes[currentNoteIndex].text; - Navigator.pop(context); + final currentNote = notes[index]; + return Dismissible( + key: Key(currentNote.name), + background: Container(color: Colors.red), + onDismissed: (direction) { + // Remove the item from the data source. + setState(() { + _deleteNote(index); + }); + + // Then show a snackbar. + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Note dismissed'))); }, + child: ListTile( + tileColor: currentNoteIndex == index + ? Colors.grey + : null, + title: Text(currentNote.name, + style: TextStyle( + fontSize: 30, + color: currentNoteIndex == index + ? null + : Colors.grey)), + onTap: () { + setState(() { + currentNoteIndex = index; + }); + textController.text = + notes[currentNoteIndex].text; + Navigator.pop(context); + }, + ), ); }) ], @@ -245,14 +323,14 @@ class _JournalPageState extends State { // space to fit everything. child: ListView( // Important: Remove any padding from the ListView. - padding: EdgeInsets.only(top: 50), + padding: const EdgeInsets.only(top: 50), children: [ DrawerHeader( - child: Text('Font', + child: Text('Font Size', style: GoogleFonts.raleway( textStyle: TextStyle( fontWeight: FontWeight.w400, - fontSize: 80, + fontSize: 60, color: MediaQuery.of(context).platformBrightness != Brightness.dark ? Colors.white diff --git a/test/hwyd_smoke_test.dart b/test/hwyd_smoke_test.dart index ca0fdd5..0fdc1d6 100644 --- a/test/hwyd_smoke_test.dart +++ b/test/hwyd_smoke_test.dart @@ -5,9 +5,9 @@ import 'package:hwyd/screens/journal_page.dart'; void main() { testWidgets('Hwyd smoke test', (WidgetTester tester) async { // Take the JournalPage widget out of our app safely so we can test it without the onboarding page - Widget testWidget = new MediaQuery( - data: new MediaQueryData(), - child: new MaterialApp(home: JournalPage()) + Widget testWidget = const MediaQuery( + data: MediaQueryData(), + child: MaterialApp(home: JournalPage()) ); // Load the JournalPage widget