mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-07-15 07:56:11 +08:00
202 lines
4.2 KiB
Dart
202 lines
4.2 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:gitjournal/core/note.dart';
|
|
import 'package:gitjournal/error_reporting.dart';
|
|
|
|
class ChecklistItem {
|
|
bool checked;
|
|
String text;
|
|
|
|
String? pre;
|
|
bool upperCase;
|
|
int lineNo;
|
|
|
|
ChecklistItem({
|
|
required this.checked,
|
|
required this.text,
|
|
this.pre = '',
|
|
this.upperCase = false,
|
|
this.lineNo = -1,
|
|
});
|
|
|
|
@override
|
|
String toString() => '$pre- [$_x] $text';
|
|
|
|
String get _x => checked
|
|
? upperCase
|
|
? 'X'
|
|
: 'x'
|
|
: ' ';
|
|
|
|
@override
|
|
bool operator ==(Object other) =>
|
|
identical(this, other) ||
|
|
other is ChecklistItem &&
|
|
runtimeType == other.runtimeType &&
|
|
checked == other.checked &&
|
|
text == other.text &&
|
|
pre == other.pre &&
|
|
upperCase == other.upperCase &&
|
|
lineNo == other.lineNo;
|
|
|
|
@override
|
|
int get hashCode => text.hashCode ^ pre.hashCode ^ checked.hashCode;
|
|
}
|
|
|
|
class Checklist {
|
|
static final _pattern = RegExp(
|
|
r'^(.*)- \[([ xX])\] ?(.*)$',
|
|
multiLine: false,
|
|
);
|
|
|
|
// FIXME: Added on 2020-05-01: Remove after 3-4 months
|
|
static final _oldPattern = RegExp(
|
|
r'^ *\[([ xX])\] +(.*)$',
|
|
multiLine: false,
|
|
);
|
|
|
|
Note _note;
|
|
List<ChecklistItem> items = [];
|
|
|
|
late List<String> _lines;
|
|
late bool endsWithNewLine;
|
|
|
|
Checklist(this._note) {
|
|
_lines = LineSplitter.split(_note.body).toList();
|
|
endsWithNewLine = _note.body.endsWith('\n');
|
|
|
|
for (var i = 0; i < _lines.length; i++) {
|
|
var line = _lines[i];
|
|
var oldPatMatch = _oldPattern.firstMatch(line);
|
|
if (oldPatMatch != null) {
|
|
line = '- ' + line;
|
|
}
|
|
|
|
var match = _pattern.firstMatch(line);
|
|
if (match == null) {
|
|
continue;
|
|
}
|
|
|
|
var pre = match.group(1);
|
|
var state = match.group(2);
|
|
var post = match.group(3)!;
|
|
|
|
var item = ChecklistItem(
|
|
pre: pre,
|
|
checked: state != ' ',
|
|
upperCase: state == 'X',
|
|
text: post,
|
|
lineNo: i,
|
|
);
|
|
items.add(item);
|
|
}
|
|
}
|
|
|
|
Note get note {
|
|
for (var item in items) {
|
|
_lines[item.lineNo] = item.toString();
|
|
}
|
|
_note.body = _lines.join('\n');
|
|
if (endsWithNewLine) {
|
|
_note.body += '\n';
|
|
}
|
|
return _note;
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return [
|
|
'[',
|
|
items.map((x) => x.toString()).join(', '),
|
|
']',
|
|
].join(' ');
|
|
}
|
|
|
|
ChecklistItem buildItem(bool value, String text) {
|
|
var item = ChecklistItem(checked: value, text: text);
|
|
return item;
|
|
}
|
|
|
|
void removeItem(ChecklistItem item) {
|
|
assert(items.contains(item));
|
|
|
|
var i = items.indexOf(item);
|
|
assert(i != -1);
|
|
if (i == -1) {
|
|
logException(
|
|
Exception('Checklist removeItem does not exist'),
|
|
StackTrace.current,
|
|
);
|
|
return;
|
|
}
|
|
|
|
removeAt(i);
|
|
}
|
|
|
|
ChecklistItem removeAt(int index) {
|
|
assert(index >= 0 && index <= items.length);
|
|
|
|
var item = items[index];
|
|
items.removeAt(index);
|
|
_lines.removeAt(item.lineNo);
|
|
for (var j = index; j < items.length; j++) {
|
|
items[j].lineNo -= 1;
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
void addItem(ChecklistItem item) {
|
|
assert(item.lineNo == -1);
|
|
|
|
if (items.isEmpty) {
|
|
item.lineNo = _lines.length;
|
|
items.add(item);
|
|
_lines.add(item.toString());
|
|
return;
|
|
}
|
|
|
|
var prevItem = items.last;
|
|
item.lineNo = prevItem.lineNo + 1;
|
|
items.add(item);
|
|
_lines.insert(item.lineNo, item.toString());
|
|
}
|
|
|
|
void insertItem(int index, ChecklistItem item) {
|
|
assert(index <= items.length);
|
|
if (index == 0 && items.isEmpty) {
|
|
addItem(item);
|
|
return;
|
|
}
|
|
|
|
if (index == 0) {
|
|
var nextItem = items[0];
|
|
item.lineNo = nextItem.lineNo;
|
|
_lines.insert(item.lineNo, item.toString());
|
|
|
|
for (var item in items) {
|
|
item.lineNo++;
|
|
}
|
|
items.insert(0, item);
|
|
return;
|
|
}
|
|
|
|
if (index == items.length) {
|
|
var prevItem = items.last;
|
|
item.lineNo = prevItem.lineNo + 1;
|
|
items.add(item);
|
|
_lines.insert(item.lineNo, item.toString());
|
|
return;
|
|
}
|
|
|
|
var prevItem = items[index];
|
|
item.lineNo = prevItem.lineNo;
|
|
_lines.insert(item.lineNo, item.toString());
|
|
|
|
for (var i = index; i < items.length; i++) {
|
|
items[i].lineNo++;
|
|
}
|
|
items.insert(index, item);
|
|
}
|
|
}
|