Skip to content

Commit

Permalink
FIX Improved console and process
Browse files Browse the repository at this point in the history
  • Loading branch information
TechnicJelle committed Aug 29, 2024
1 parent 9bd6135 commit f1f900a
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Make sure you have **Java 16** or higher installed and on your PATH!

## TODO
- make the console better
- fix the scroll; when you scroll up, new logs should not move the view (but it does, rn)
- add a scroll down button (only visible if you scroll up)
- fix the random line breaks (probably due to the stream)
- make the start/stop buttons a single button
- make it not lose the process (orphan) as easily
- when going to a config file without stopping the bluemap process, it loses it and you have to restart it
- when closing the program, it loses it
Expand Down
26 changes: 12 additions & 14 deletions lib/console.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ class ConsoleState extends ConsumerState<Console> {

@override
Widget build(BuildContext context) {
final AsyncValue<String> asyncLog = ref.watch(logProvider);
switch (asyncLog) {
case AsyncData(value: final String message):
print("RECEIVE: $message");
output.add(message);
break;
case AsyncError(:final error):
print("ERR: $error");
output.add("ERR: $error");
break;
default:
print("No new log message");
break;
}
ref.listen(logNotifierProvider, (_, next) {
switch (next) {
case AsyncData(value: final String? message):
if (message != null) {
setState(() => output.add(message));
}
break;
case AsyncError(:final error):
setState(() => output.add("ERR: $error"));
break;
}
});

return Container(
margin: const EdgeInsets.only(bottom: 8, right: 8),
Expand Down
117 changes: 52 additions & 65 deletions lib/control_panel.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "dart:async";
import "dart:convert";
import "dart:io";

Expand All @@ -10,23 +11,12 @@ import "package:url_launcher/url_launcher.dart";
import "console.dart";
import "main.dart";

class LogNotifier extends AsyncNotifier<String> {
class LogNotifier extends AutoDisposeAsyncNotifier<String?> {
Process? _process;
StreamSubscription? _streamSub;
@override
String build() {
return "";
}

void log(String message) {
state = AsyncValue.data(message);
}
}

final logProvider = AsyncNotifierProvider<LogNotifier, String>(() => LogNotifier());

class ProcessNotifier extends AsyncNotifier<Process?> {
@override
Future<Process?> build() {
return Future.value(null);
Future<String?> build() async {
return null;
}

Future<void> start() async {
Expand All @@ -35,63 +25,60 @@ class ProcessNotifier extends AsyncNotifier<Process?> {
final Directory projectDirectory = ref.read(projectDirectoryProvider)!;
final String bluemapJarPath = p.join(projectDirectory.path, blueMapCliJarName);

state = await AsyncValue.guard(() async {
Process process = await Process.start(
"java",
["-jar", bluemapJarPath, "--render", "--watch", "--webserver"],
workingDirectory: projectDirectory.path,
mode: ProcessStartMode.normal,
runInShell: false,
);
process.exitCode.then((value) {
print("Exit code: $value");
state = const AsyncValue.data(null);
return;
});

var mergedStream = StreamGroup.merge([
process.stdout.transform(utf8.decoder),
process.stderr.transform(utf8.decoder),
]);

mergedStream.listen((String event) {
print("OUTPUT: $event");
ref.read(logProvider.notifier).log(event);
});

// bool hasWebserverStartedYet = false;
// process.stdout.transform(utf8.decoder).listen((String event) {
// if (event.contains("WebServer started")) {
// hasWebserverStartedYet = true;
// }
// });
//
// while (!hasWebserverStartedYet) {
// await Future.delayed(const Duration(milliseconds: 100));
// }
final process = await Process.start(
"java",
["-jar", bluemapJarPath, "--render", "--watch", "--webserver"],
workingDirectory: projectDirectory.path,
mode: ProcessStartMode.normal,
runInShell: false,
);
process.exitCode.then((value) {
print("Exit code: $value");
state = const AsyncValue.data(null);
return;
});

return process;
var mergedStream = StreamGroup.merge([
process.stdout.transform(utf8.decoder),
process.stderr.transform(utf8.decoder),
]);

// bool hasWebserverStartedYet = false;
// process.stdout.transform(utf8.decoder).listen((String event) {
// if (event.contains("WebServer started")) {
// hasWebserverStartedYet = true;
// }
// });
//
// while (!hasWebserverStartedYet) {
// await Future.delayed(const Duration(milliseconds: 100));
// }

_process = process;
_streamSub?.cancel();
_streamSub = mergedStream.listen((String event) {
print("OUTPUT: $event");
state = AsyncValue.data(event);
});
}

void stop() {
state.whenData((Process? process) {
if (process == null) throw Exception("No process to stop!");
process.kill();
});
Process? process = _process;
if (process == null) throw Exception("No process to stop!");
process.kill();
_streamSub?.cancel();
}
}

final processProvider =
AsyncNotifierProvider<ProcessNotifier, Process?>(() => ProcessNotifier());
final logNotifierProvider =
AsyncNotifierProvider.autoDispose<LogNotifier, String?>(() => LogNotifier());

class ControlPanel extends ConsumerWidget {
const ControlPanel({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final asyncProcess = ref.watch(processProvider);
final Process? process = asyncProcess.asData?.value;
final logMessage = ref.watch(logNotifierProvider).value;

return Padding(
padding: const EdgeInsets.only(top: 16),
Expand All @@ -103,18 +90,18 @@ class ControlPanel extends ConsumerWidget {
children: [
ElevatedButton.icon(
onPressed: () {
if (process == null) {
ref.read(processProvider.notifier).start();
if (logMessage == null) {
ref.read(logNotifierProvider.notifier).start();
} else {
ref.read(processProvider.notifier).stop();
ref.read(logNotifierProvider.notifier).stop();
}
},
label: Text(process == null ? "Start" : "Stop"),
icon: Icon(process == null ? Icons.play_arrow : Icons.stop),
label: Text(logMessage == null ? "Start" : "Stop"),
icon: Icon(logMessage == null ? Icons.play_arrow : Icons.stop),
),
const SizedBox(width: 16),
ElevatedButton.icon(
onPressed: process == null
onPressed: logMessage == null
? null
: () async {
if (!await launchUrl(Uri.parse("http://localhost:8100"))) {
Expand Down

0 comments on commit f1f900a

Please sign in to comment.