preserve notes

This commit is contained in:
Sarah Jamie Lewis 2022-10-08 19:26:31 -07:00
parent 6aac11934f
commit 3ed60ca3d8
5 changed files with 65 additions and 57 deletions

1
.gitignore vendored
View File

@ -43,3 +43,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
*.notes

View File

@ -13,7 +13,6 @@ class Editor extends StatefulWidget {
class _Editor extends State<Editor> {
@override
Widget build(BuildContext context) {
return InputListener(LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
//print("opening document " + path + " " + startLine.toString());
return View();

View File

@ -31,6 +31,16 @@ class LineFile extends ChangeNotifier {
line += 1;
});
File notesFile = File("$path.subwrite.notes");
if (notesFile.existsSync()) {
notesFile.readAsLinesSync().forEach((notetext) {
var parts = notetext.split(":");
var line = int.parse(parts[0]);
var note = parts.sublist(1).join(":");
addNoteAtLine(line, note);
});
}
// handle the empty file case
if (backingLines.isEmpty) {
backingLines.insert(0, LineInfo(path, 1, ""));
@ -115,9 +125,17 @@ class LineFile extends ChangeNotifier {
void saveFile() {
String content = '';
String notes = '';
for (var l in backingLines) {
content += '${l.text}\n';
for (var annot in l.annotations) {
if (annot.description != null) {
notes += '${annot.sourceLink.lineStart}:${annot.description}\n';
}
}
}
File("$path.subwrite.notes").writeAsStringSync(notes);
File(path).writeAsStringSync(content);
}
@ -379,6 +397,10 @@ class LineFile extends ChangeNotifier {
}
addNote(String note) {
addNoteAtLine(cursor.line, note);
}
addNoteAtLine(int line, String note) {
var notetype = "note";
if (note.startsWith("[incomplete]")) {
notetype = "incomplete";
@ -386,10 +408,10 @@ class LineFile extends ChangeNotifier {
notetype = "edit";
}
backingLines[cursor.line - 1].annotations.add(LineAnnotation(
backingLines[line - 1].annotations.add(LineAnnotation(
SourceLink(
path,
lineStart: cursor.line,
lineStart: line,
),
"notes",
AnnotationType.note,

View File

@ -46,7 +46,6 @@ class LineInfo extends ChangeNotifier {
List<Widget> stackElements = List.empty(growable: true);
var charWidth = (fontSize / 2.0);
var lineHeight = (fontSize * 1.2);
var usableSize = (constraints.maxWidth - gutterWidth - rightMargin - leftMargin);
@ -88,16 +87,13 @@ class LineInfo extends ChangeNotifier {
var cursorPosTop = (cursorStart! / maxCharsBeforeWrapping).floorToDouble() * lineHeight;
var cursorPosLeft = ((cursorStart! % maxCharsBeforeWrapping) * charWidth) - charWidth / 2.0;
TextStyle cursorStyle = TextStyle(fontFamily: 'Iosevka', fontSize: fontSize, color: foreground, backgroundColor: Colors.transparent, letterSpacing: -2.0);
var cursorPos = Positioned(top: cursorPosTop.toDouble(), left: leftMargin+cursorPosLeft.toDouble(), child: FadeTransition(
opacity: animationController, child: Text("|", style: cursorStyle)));
stackElements.add( cursorPos);
var cursorPos =
Positioned(top: cursorPosTop.toDouble(), left: leftMargin + cursorPosLeft.toDouble(), child: FadeTransition(opacity: animationController, child: Text("|", style: cursorStyle)));
stackElements.add(cursorPos);
}
var cursorOverlay = Stack(children: stackElements);
return Listener(
onPointerDown: (event) {
var inMargin = (event.localPosition.dx - gutterWidth) > usableSize;
@ -158,7 +154,7 @@ class LineInfo extends ChangeNotifier {
margin: EdgeInsets.only(right: 1, top: 0, bottom: 0, left: 0),
alignment: Alignment.centerLeft,
child: Flex(direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.start, children: sidebarContent)),
cursorOverlay,
cursorOverlay,
]))));
},
);

View File

@ -11,21 +11,18 @@ import 'line_info.dart';
class View extends StatefulWidget {
View({Key? key}) : super(key: key);
@override
_View createState() => _View();
}
class _View extends State<View> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
_animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
_animationController.repeat(reverse: true);
}
@override
@ -40,53 +37,47 @@ class _View extends State<View> with SingleTickerProviderStateMixin {
if (doc.backingLines.isEmpty) {
return Center(
child: Row (
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton.icon(
onPressed: () async {
String? result = await FilePicker.platform.saveFile();
ElevatedButton.icon(onPressed: () async {
String? result = await FilePicker.platform.saveFile(
);
if (result != null) {
File(result).createSync(recursive: false);
doc.openFile(result, 0);
doc.focus.requestFocus();
} else {
// User canceled the picker
}
}, icon: Icon(Icons.create, color: foreground), label: const Text("New Document"),
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(tabs),
foregroundColor: MaterialStateProperty.all(foreground))),
SizedBox(width: 20,),
ElevatedButton.icon(onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
allowMultiple: false,
type: FileType.custom,
allowedExtensions: ['md','txt'],
);
if (result != null) {
doc.openFile(result.files.single.path!, 0);
} else {
// User canceled the picker
}
}, icon: Icon(Icons.file_open, color: foreground), label: const Text("Open Document"),
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(tabs),
foregroundColor: MaterialStateProperty.all(foreground))),
if (result != null) {
File(result).createSync(recursive: false);
doc.openFile(result, 0);
doc.focus.requestFocus();
} else {
// User canceled the picker
}
},
icon: Icon(Icons.create, color: foreground),
label: const Text("New Document"),
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(tabs), foregroundColor: MaterialStateProperty.all(foreground))),
SizedBox(
width: 20,
),
ElevatedButton.icon(
onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
allowMultiple: false,
type: FileType.custom,
allowedExtensions: ['md', 'txt'],
);
if (result != null) {
doc.openFile(result.files.single.path!, 0);
} else {
// User canceled the picker
}
},
icon: Icon(Icons.file_open, color: foreground),
label: const Text("Open Document"),
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(tabs), foregroundColor: MaterialStateProperty.all(foreground))),
],
),
);
} else {
return ScrollablePositionedList.builder(
physics: const AlwaysScrollableScrollPhysics(),
@ -98,8 +89,7 @@ class _View extends State<View> with SingleTickerProviderStateMixin {
return ChangeNotifierProvider.value(
value: doc.backingLines[index],
builder: (lcontext, lineinfo) {
return Provider.of<LineInfo>(lcontext).build(
context, _animationController);
return Provider.of<LineInfo>(lcontext).build(context, _animationController);
});
});
}