Async progress bar for longer running tasks
This commit is contained in:
parent
521aa85cbe
commit
fccc925740
|
@ -1,6 +1,7 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
import 'dart:async';
|
||||
import 'dart:isolate';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -27,7 +28,34 @@ class LineFile extends ChangeNotifier {
|
|||
|
||||
var showSuggestions = false;
|
||||
|
||||
final SpellChecker spellchecker = SpellChecker.load("dicts/english.txt");
|
||||
SpellChecker? spellchecker;
|
||||
|
||||
buildDictionary() async {
|
||||
ReceivePort receivePort = ReceivePort();
|
||||
|
||||
receivePort.listen((dynamic message) {
|
||||
updateStatus(message as double);
|
||||
});
|
||||
|
||||
status = "loading dictionary";
|
||||
notifyListeners();
|
||||
|
||||
compute(SpellChecker.load, DictionaryLoadRequest("dicts/english.txt", receivePort.sendPort)).then(
|
||||
(value) {
|
||||
spellchecker = value;
|
||||
status = "dictionary loaded";
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void updateStatus(double update) {
|
||||
statusProgress = update;
|
||||
print("New Progress Status...$statusProgress");
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
double statusProgress = 0.0;
|
||||
|
||||
void cancelSuggestions() {
|
||||
suggestionIndex = 0;
|
||||
|
@ -196,8 +224,12 @@ class LineFile extends ChangeNotifier {
|
|||
showSuggestions = false;
|
||||
notifyListeners();
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.f4) {
|
||||
status = "spellchecking document";
|
||||
notifyListeners();
|
||||
updateStatus(0.0);
|
||||
spellCheckAll().then((value) {
|
||||
status = "spellcheck complete";
|
||||
notifyListeners();
|
||||
});
|
||||
} else {
|
||||
if (event.isControlPressed) {
|
||||
|
@ -387,6 +419,10 @@ class LineFile extends ChangeNotifier {
|
|||
var line = backingLines[i];
|
||||
line.annotations.removeWhere((element) => element.tool == "spellcheck");
|
||||
|
||||
if (spellchecker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<LineAnnotation> annotations = List.empty(growable: true);
|
||||
var wordStart = 0;
|
||||
var wordEnd = 0;
|
||||
|
@ -443,20 +479,20 @@ class LineFile extends ChangeNotifier {
|
|||
continue;
|
||||
}
|
||||
|
||||
HashSet<String>? candidates = spellchecker.candidates(word);
|
||||
HashSet<String>? candidates = spellchecker!.candidates(word);
|
||||
if (candidates == null) {
|
||||
await compute(mutations2, word).then((results) {
|
||||
spellchecker.dictionary.putIfAbsent(word, () => HashSet());
|
||||
spellchecker!.dictionary.putIfAbsent(word, () => HashSet());
|
||||
results.forEach((element) {
|
||||
if (spellchecker.known.contains(element)) {
|
||||
spellchecker.dictionary[word]!.add(element);
|
||||
if (spellchecker!.known.contains(element)) {
|
||||
spellchecker!.dictionary[word]!.add(element);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Candidates should now not be null...
|
||||
candidates = spellchecker.candidates(word);
|
||||
candidates = spellchecker!.candidates(word);
|
||||
if (candidates!.contains(word) == false) {
|
||||
annotations.add(LineAnnotation(SourceLink("", lineStart: 0, colStart: annotationStart, colEnd: wordEnd + 1, lineEnd: 0), "spellcheck", AnnotationType.highlight, "spellcheck",
|
||||
description: "${candidates.join(":")}:$word"));
|
||||
|
@ -644,12 +680,13 @@ class LineFile extends ChangeNotifier {
|
|||
Future<bool> spellCheckAll() async {
|
||||
for (int i = 0; i < backingLines.length; i++) {
|
||||
await spellcheck(i);
|
||||
updateStatus(i.toDouble() / backingLines.length.toDouble());
|
||||
}
|
||||
return Future.value(true);
|
||||
}
|
||||
|
||||
customDic(BuildContext context, Suggestion suggestion) {
|
||||
spellchecker.addToCustomDictionary(suggestion.name);
|
||||
spellchecker!.addToCustomDictionary(suggestion.name);
|
||||
int line = suggestion.link.lineStart! - 1;
|
||||
spellcheck(line);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'outline.dart';
|
|||
|
||||
void main(List<String> args) {
|
||||
var docfile = LineFile();
|
||||
docfile.buildDictionary();
|
||||
if (args.length > 0) {
|
||||
docfile.openFile(args[0], 0);
|
||||
}
|
||||
|
@ -72,17 +73,30 @@ class _SarahDownApp extends State<SarahDownApp> {
|
|||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 5.0),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text(
|
||||
"${Provider.of<LineFile>(context).status}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Iosevka',
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: foreground,
|
||||
backgroundColor: Colors.transparent,
|
||||
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: LinearProgressIndicator(
|
||||
color: comment,
|
||||
backgroundColor: sidebar,
|
||||
value: Provider.of<LineFile>(context).statusProgress,
|
||||
minHeight: 5.0,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${Provider.of<LineFile>(context).status}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Iosevka',
|
||||
fontSize: 8,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: foreground,
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
]),
|
||||
Text(
|
||||
"Word Count: ${Provider.of<LineFile>(context).wordCount()}",
|
||||
textAlign: TextAlign.right,
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class DictionaryLoadRequest {
|
||||
String dictPath;
|
||||
SendPort callback;
|
||||
DictionaryLoadRequest(this.dictPath, this.callback);
|
||||
}
|
||||
|
||||
class SpellChecker {
|
||||
HashMap<String, HashSet<String>> dictionary;
|
||||
HashSet<String> known;
|
||||
|
@ -10,13 +17,17 @@ class SpellChecker {
|
|||
|
||||
SpellChecker(this.dictionary, this.known, this.custom);
|
||||
|
||||
static SpellChecker load(String dictPath) {
|
||||
static SpellChecker load(DictionaryLoadRequest request) {
|
||||
HashMap<String, HashSet<String>> dictionary = HashMap();
|
||||
HashSet<String> known = HashSet();
|
||||
HashSet<String> custom = HashSet();
|
||||
File dict = File(dictPath);
|
||||
File dict = File(request.dictPath);
|
||||
|
||||
var lines = dict.readAsLinesSync();
|
||||
|
||||
print("building dictionary...");
|
||||
dict.readAsLinesSync().forEach((word) {
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
var word = lines[i];
|
||||
var lower = word.toLowerCase().trim();
|
||||
dictionary.putIfAbsent(lower, () => HashSet.from([lower]));
|
||||
known.add(lower);
|
||||
|
@ -25,7 +36,11 @@ class SpellChecker {
|
|||
dictionary.putIfAbsent(element, () => HashSet());
|
||||
dictionary[element]!.add(lower);
|
||||
});
|
||||
});
|
||||
|
||||
if (i % 1000 == 0) {
|
||||
request.callback.send(i.toDouble() / lines.length);
|
||||
}
|
||||
}
|
||||
|
||||
File customdict = File("subwrite.custom.dictionary.txt");
|
||||
print("building custom dictionary...");
|
||||
|
@ -43,6 +58,8 @@ class SpellChecker {
|
|||
});
|
||||
}
|
||||
|
||||
// finished!
|
||||
request.callback.send(1.0);
|
||||
print("built dictionary...${dictionary.length}");
|
||||
return SpellChecker(dictionary, known, custom);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ decrypted
|
|||
adversary
|
||||
replying
|
||||
plaintext
|
||||
weirdly
|
||||
bypassed
|
||||
weirdly
|
||||
leaked
|
||||
fuzzing
|
||||
decrypt
|
||||
stash
|
||||
encrypt
|
||||
ciphertext
|
||||
decrypting
|
||||
|
|
Loading…
Reference in New Issue