mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 18:03:14 +08:00
Use an InheritedWidget instead of passing the callbacks
This simplifies the code quite a bit, at the cost of using this strange flutter magic of an 'InheritedWidget'. It basically make a class a global variable.
This commit is contained in:
72
lib/app.dart
72
lib/app.dart
@ -1,51 +1,14 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
import 'package:journal/file_storage.dart';
|
|
||||||
import 'package:journal/note.dart';
|
|
||||||
import 'package:journal/screens/home_screen.dart';
|
import 'package:journal/screens/home_screen.dart';
|
||||||
|
|
||||||
class JournalApp extends StatefulWidget {
|
class JournalApp extends StatelessWidget {
|
||||||
final FileStorage fileStorage;
|
JournalApp();
|
||||||
|
|
||||||
JournalApp({@required this.fileStorage});
|
|
||||||
|
|
||||||
@override
|
|
||||||
JournalAppState createState() {
|
|
||||||
return new JournalAppState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JournalAppState extends State<JournalApp> {
|
|
||||||
AppState appState = AppState.loading();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
widget.fileStorage.loadNotes().then((loadedNotes) {
|
|
||||||
setState(() {
|
|
||||||
appState = AppState(notes: loadedNotes);
|
|
||||||
});
|
|
||||||
}).catchError((err) {
|
|
||||||
setState(() {
|
|
||||||
print("Got Error");
|
|
||||||
print(err);
|
|
||||||
appState.isLoading = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new MaterialApp(
|
return new MaterialApp(
|
||||||
title: 'Journal',
|
title: 'Journal',
|
||||||
home: new HomeScreen(
|
home: new HomeScreen(),
|
||||||
appState: appState,
|
|
||||||
noteAdder: addNote,
|
|
||||||
noteRemover: removeNote,
|
|
||||||
),
|
|
||||||
theme: new ThemeData(
|
theme: new ThemeData(
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
primaryColor: Colors.lightBlue[800],
|
primaryColor: Colors.lightBlue[800],
|
||||||
@ -53,33 +16,4 @@ class JournalAppState extends State<JournalApp> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void setState(VoidCallback fn) {
|
|
||||||
super.setState(fn);
|
|
||||||
|
|
||||||
widget.fileStorage.saveNotes(appState.notes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNote(Note note) {
|
|
||||||
print("Adding a note " + note.toString());
|
|
||||||
setState(() {
|
|
||||||
note.id = new Uuid().v4();
|
|
||||||
appState.notes.insert(0, note);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeNote(Note note) {
|
|
||||||
setState(() {
|
|
||||||
appState.notes.remove(note);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Implement this!
|
|
||||||
void updateNote(Note note) {
|
|
||||||
setState(() {
|
|
||||||
//appState.notes.
|
|
||||||
//appState.notes.remove(note);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import './note.dart';
|
|||||||
class FileStorage {
|
class FileStorage {
|
||||||
final Future<Directory> Function() getDirectory;
|
final Future<Directory> Function() getDirectory;
|
||||||
|
|
||||||
FileStorage({@required this.getDirectory});
|
const FileStorage({@required this.getDirectory});
|
||||||
|
|
||||||
Future<List<Note>> loadNotes() async {
|
Future<List<Note>> loadNotes() async {
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
//import 'package:http/http.dart' as http;
|
//import 'package:http/http.dart' as http;
|
||||||
import 'package:journal/app.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
|
||||||
import 'package:journal/file_storage.dart';
|
import 'package:journal/app.dart';
|
||||||
|
import 'package:journal/state_container.dart';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
import 'note.dart';
|
import 'note.dart';
|
||||||
@ -26,17 +21,7 @@ Future<List<Note>> fetchNotes() async {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(new JournalApp(
|
runApp(new StateContainer(
|
||||||
fileStorage: FileStorage(
|
child: JournalApp(),
|
||||||
getDirectory: getNotesDir,
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Directory> getNotesDir() async {
|
|
||||||
var appDir = await getApplicationDocumentsDirectory();
|
|
||||||
var dir = new Directory(p.join(appDir.path, "notes"));
|
|
||||||
await dir.create();
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
|
import 'package:journal/state_container.dart';
|
||||||
|
|
||||||
class NoteEditor extends StatelessWidget {
|
class NoteEditor extends StatelessWidget {
|
||||||
static final GlobalKey<FormFieldState<String>> noteTextKey =
|
static final GlobalKey<FormFieldState<String>> noteTextKey =
|
||||||
GlobalKey<FormFieldState<String>>();
|
GlobalKey<FormFieldState<String>>();
|
||||||
final NoteAdder noteAdder;
|
|
||||||
final DateTime _createdAt;
|
final DateTime _createdAt;
|
||||||
|
|
||||||
NoteEditor({
|
NoteEditor() : _createdAt = new DateTime.now();
|
||||||
@required this.noteAdder,
|
|
||||||
}) : _createdAt = new DateTime.now();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final container = StateContainer.of(context);
|
||||||
|
|
||||||
var bodyWidget = new Container(
|
var bodyWidget = new Container(
|
||||||
child: new TextFormField(
|
child: new TextFormField(
|
||||||
key: noteTextKey,
|
key: noteTextKey,
|
||||||
@ -44,7 +43,7 @@ class NoteEditor extends StatelessWidget {
|
|||||||
createdAt: _createdAt,
|
createdAt: _createdAt,
|
||||||
body: body,
|
body: body,
|
||||||
);
|
);
|
||||||
noteAdder(note);
|
container.addNote(note);
|
||||||
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}),
|
}),
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
import 'package:journal/state_container.dart';
|
||||||
import 'package:journal/widgets/journal_list.dart';
|
import 'package:journal/widgets/journal_list.dart';
|
||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
import 'package:journal/note_editor.dart';
|
import 'package:journal/note_editor.dart';
|
||||||
import 'package:journal/note_viewer.dart';
|
import 'package:journal/note_viewer.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatelessWidget {
|
class HomeScreen extends StatelessWidget {
|
||||||
final AppState appState;
|
|
||||||
final NoteAdder noteAdder;
|
|
||||||
final NoteRemover noteRemover;
|
|
||||||
|
|
||||||
HomeScreen({
|
|
||||||
@required this.appState,
|
|
||||||
@required this.noteAdder,
|
|
||||||
@required this.noteRemover,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final container = StateContainer.of(context);
|
||||||
|
final appState = container.appState;
|
||||||
|
|
||||||
var createButton = new FloatingActionButton(
|
var createButton = new FloatingActionButton(
|
||||||
onPressed: () => _newPost(context),
|
onPressed: () => _newPost(context),
|
||||||
child: new Icon(Icons.add),
|
child: new Icon(Icons.add),
|
||||||
@ -49,7 +43,6 @@ class HomeScreen extends StatelessWidget {
|
|||||||
body: new JournalList(
|
body: new JournalList(
|
||||||
notes: appState.notes,
|
notes: appState.notes,
|
||||||
noteSelectedFunction: (note) => _noteSelected(note, context),
|
noteSelectedFunction: (note) => _noteSelected(note, context),
|
||||||
noteRemover: noteRemover,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -61,10 +54,7 @@ class HomeScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _newPost(BuildContext context) {
|
void _newPost(BuildContext context) {
|
||||||
var route = new MaterialPageRoute(
|
var route = new MaterialPageRoute(builder: (context) => new NoteEditor());
|
||||||
builder: (context) => new NoteEditor(
|
|
||||||
noteAdder: noteAdder,
|
|
||||||
));
|
|
||||||
Navigator.of(context).push(route);
|
Navigator.of(context).push(route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
117
lib/state_container.dart
Normal file
117
lib/state_container.dart
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
import 'package:journal/note.dart';
|
||||||
|
import 'package:journal/file_storage.dart';
|
||||||
|
|
||||||
|
Future<Directory> getNotesDir() async {
|
||||||
|
var appDir = await getApplicationDocumentsDirectory();
|
||||||
|
var dir = new Directory(p.join(appDir.path, "notes"));
|
||||||
|
await dir.create();
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StateContainer extends StatefulWidget {
|
||||||
|
final FileStorage fileStorage;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
StateContainer({
|
||||||
|
@required this.child,
|
||||||
|
this.fileStorage = const FileStorage(
|
||||||
|
getDirectory: getNotesDir,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
static StateContainerState of(BuildContext context) {
|
||||||
|
return (context.inheritFromWidgetOfExactType(_InheritedStateContainer)
|
||||||
|
as _InheritedStateContainer)
|
||||||
|
.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return StateContainerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StateContainerState extends State<StateContainer> {
|
||||||
|
AppState appState = AppState.loading();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
widget.fileStorage.loadNotes().then((loadedNotes) {
|
||||||
|
setState(() {
|
||||||
|
appState = AppState(notes: loadedNotes);
|
||||||
|
});
|
||||||
|
}).catchError((err) {
|
||||||
|
setState(() {
|
||||||
|
print("Got Error");
|
||||||
|
print(err);
|
||||||
|
appState.isLoading = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setState(VoidCallback fn) {
|
||||||
|
super.setState(fn);
|
||||||
|
|
||||||
|
widget.fileStorage.saveNotes(appState.notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addNote(Note note) {
|
||||||
|
print("Adding a note " + note.toString());
|
||||||
|
setState(() {
|
||||||
|
note.id = new Uuid().v4();
|
||||||
|
appState.notes.insert(0, note);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeNote(Note note) {
|
||||||
|
setState(() {
|
||||||
|
appState.notes.remove(note);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Implement this!
|
||||||
|
void updateNote(Note note) {
|
||||||
|
setState(() {
|
||||||
|
//appState.notes.
|
||||||
|
//appState.notes.remove(note);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return _InheritedStateContainer(
|
||||||
|
data: this,
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InheritedStateContainer extends InheritedWidget {
|
||||||
|
final StateContainerState data;
|
||||||
|
|
||||||
|
_InheritedStateContainer({
|
||||||
|
Key key,
|
||||||
|
@required this.data,
|
||||||
|
@required Widget child,
|
||||||
|
}) : super(key: key, child: child);
|
||||||
|
|
||||||
|
// Note: we could get fancy here and compare whether the old AppState is
|
||||||
|
// different than the current AppState. However, since we know this is the
|
||||||
|
// root Widget, when we make changes we also know we want to rebuild Widgets
|
||||||
|
// that depend on the StateContainer.
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(_InheritedStateContainer old) => true;
|
||||||
|
}
|
@ -3,12 +3,12 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
|
import 'package:journal/state_container.dart';
|
||||||
|
|
||||||
typedef void NoteSelectedFunction(Note note);
|
typedef void NoteSelectedFunction(Note note);
|
||||||
|
|
||||||
class JournalList extends StatelessWidget {
|
class JournalList extends StatelessWidget {
|
||||||
final NoteSelectedFunction noteSelectedFunction;
|
final NoteSelectedFunction noteSelectedFunction;
|
||||||
final NoteRemover noteRemover;
|
|
||||||
final List<Note> notes;
|
final List<Note> notes;
|
||||||
|
|
||||||
final _biggerFont = const TextStyle(fontSize: 18.0);
|
final _biggerFont = const TextStyle(fontSize: 18.0);
|
||||||
@ -16,11 +16,12 @@ class JournalList extends StatelessWidget {
|
|||||||
JournalList({
|
JournalList({
|
||||||
@required this.notes,
|
@required this.notes,
|
||||||
@required this.noteSelectedFunction,
|
@required this.noteSelectedFunction,
|
||||||
@required this.noteRemover,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final container = StateContainer.of(context);
|
||||||
|
|
||||||
return new ListView.builder(
|
return new ListView.builder(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
@ -35,7 +36,7 @@ class JournalList extends StatelessWidget {
|
|||||||
child: _buildRow(context, note),
|
child: _buildRow(context, note),
|
||||||
background: new Container(color: Colors.red),
|
background: new Container(color: Colors.red),
|
||||||
onDismissed: (direction) {
|
onDismissed: (direction) {
|
||||||
noteRemover(note);
|
container.removeNote(note);
|
||||||
|
|
||||||
Scaffold
|
Scaffold
|
||||||
.of(context)
|
.of(context)
|
||||||
|
Reference in New Issue
Block a user