mirror of
https://github.com/DefinedNet/mobile_nebula.git
synced 2025-02-12 06:55:27 +00:00
Don't pop an error when there is no logs file (#245)
This commit is contained in:
parent
d3e5291944
commit
f2c4b07154
3 changed files with 103 additions and 28 deletions
|
@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||||
import 'package:mobile_nebula/components/SimplePage.dart';
|
import 'package:mobile_nebula/components/SimplePage.dart';
|
||||||
import 'package:mobile_nebula/models/Site.dart';
|
import 'package:mobile_nebula/models/Site.dart';
|
||||||
|
import 'package:mobile_nebula/services/logs.dart';
|
||||||
|
import 'package:mobile_nebula/services/result.dart';
|
||||||
import 'package:mobile_nebula/services/settings.dart';
|
import 'package:mobile_nebula/services/settings.dart';
|
||||||
import 'package:mobile_nebula/services/share.dart';
|
import 'package:mobile_nebula/services/share.dart';
|
||||||
import 'package:mobile_nebula/services/utils.dart';
|
import 'package:mobile_nebula/services/utils.dart';
|
||||||
|
@ -22,14 +24,14 @@ class SiteLogsScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SiteLogsScreenState extends State<SiteLogsScreen> {
|
class _SiteLogsScreenState extends State<SiteLogsScreen> {
|
||||||
String logs = '';
|
final ScrollController controller = ScrollController();
|
||||||
ScrollController controller = ScrollController();
|
final RefreshController refreshController = RefreshController(initialRefresh: false);
|
||||||
RefreshController refreshController = RefreshController(initialRefresh: false);
|
final LogsNotifier logsNotifier = LogsNotifier();
|
||||||
|
|
||||||
var settings = Settings();
|
var settings = Settings();
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
loadLogs();
|
logsNotifier.loadLogs(logFile: widget.site.logFile);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,18 +51,29 @@ class _SiteLogsScreenState extends State<SiteLogsScreen> {
|
||||||
scrollable: SimpleScrollable.both,
|
scrollable: SimpleScrollable.both,
|
||||||
scrollController: controller,
|
scrollController: controller,
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await loadLogs();
|
await logsNotifier.loadLogs(logFile: widget.site.logFile);
|
||||||
refreshController.refreshCompleted();
|
refreshController.refreshCompleted();
|
||||||
},
|
},
|
||||||
onLoading: () async {
|
onLoading: () async {
|
||||||
await loadLogs();
|
await logsNotifier.loadLogs(logFile: widget.site.logFile);
|
||||||
refreshController.loadComplete();
|
refreshController.loadComplete();
|
||||||
},
|
},
|
||||||
refreshController: refreshController,
|
refreshController: refreshController,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(5),
|
padding: EdgeInsets.all(5),
|
||||||
constraints: logBoxConstraints(context),
|
constraints: logBoxConstraints(context),
|
||||||
child: SelectableText(logs.trim(), style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14))),
|
child: ListenableBuilder(
|
||||||
|
listenable: logsNotifier,
|
||||||
|
builder: (context, child) => SelectableText(
|
||||||
|
switch (logsNotifier.logsResult) {
|
||||||
|
Ok<String>(:var value) => value.trim(),
|
||||||
|
Error<String>(:var error) => error is LogsNotFoundException
|
||||||
|
? error.error()
|
||||||
|
: Utils.popError(context, "Error while reading logs.", error.toString()),
|
||||||
|
null => "",
|
||||||
|
},
|
||||||
|
style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14)),
|
||||||
|
)),
|
||||||
bottomBar: _buildBottomBar(),
|
bottomBar: _buildBottomBar(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -143,27 +156,6 @@ class _SiteLogsScreenState extends State<SiteLogsScreen> {
|
||||||
material: (context, child, platform) => BottomAppBar(child: child));
|
material: (context, child, platform) => BottomAppBar(child: child));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadLogs() async {
|
|
||||||
var file = File(widget.site.logFile);
|
|
||||||
try {
|
|
||||||
final v = await file.readAsString();
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
logs = v;
|
|
||||||
});
|
|
||||||
} on FileSystemException {
|
|
||||||
Utils.popError(context, 'Error while reading logs', 'No log file was present');
|
|
||||||
} catch (err) {
|
|
||||||
Utils.popError(context, 'Error while reading logs', err.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteLogs() async {
|
|
||||||
var file = File(widget.site.logFile);
|
|
||||||
await file.writeAsBytes([]);
|
|
||||||
await loadLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
logBoxConstraints(BuildContext context) {
|
logBoxConstraints(BuildContext context) {
|
||||||
if (settings.logWrap) {
|
if (settings.logWrap) {
|
||||||
return BoxConstraints(maxWidth: MediaQuery.of(context).size.width);
|
return BoxConstraints(maxWidth: MediaQuery.of(context).size.width);
|
||||||
|
|
31
lib/services/logs.dart
Normal file
31
lib/services/logs.dart
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:mobile_nebula/services/result.dart';
|
||||||
|
|
||||||
|
class LogsNotFoundException implements Exception {
|
||||||
|
String error() => 'No logs found. Logs will be available after starting the site for the first time.';
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogsNotifier extends ChangeNotifier {
|
||||||
|
Result<String>? logsResult;
|
||||||
|
|
||||||
|
LogsNotifier();
|
||||||
|
|
||||||
|
loadLogs({required String logFile}) async {
|
||||||
|
final file = File(logFile);
|
||||||
|
try {
|
||||||
|
logsResult = Result.ok(await file.readAsString());
|
||||||
|
notifyListeners();
|
||||||
|
} on FileSystemException {
|
||||||
|
logsResult = Result.error(LogsNotFoundException());
|
||||||
|
notifyListeners();
|
||||||
|
} on Exception catch (err) {
|
||||||
|
logsResult = Result.error(err);
|
||||||
|
notifyListeners();
|
||||||
|
} catch (err) {
|
||||||
|
logsResult = Result.error(Exception(err));
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
lib/services/result.dart
Normal file
52
lib/services/result.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/// Utility class that simplifies handling errors.
|
||||||
|
///
|
||||||
|
/// Return a [Result] from a function to indicate success or failure.
|
||||||
|
///
|
||||||
|
/// A [Result] is either an [Ok] with a value of type [T]
|
||||||
|
/// or an [Error] with an [Exception].
|
||||||
|
///
|
||||||
|
/// Use [Result.ok] to create a successful result with a value of type [T].
|
||||||
|
/// Use [Result.error] to create an error result with an [Exception].
|
||||||
|
///
|
||||||
|
/// Evaluate the result using a switch statement:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (result) {
|
||||||
|
/// case Ok(): {
|
||||||
|
/// print(result.value);
|
||||||
|
/// }
|
||||||
|
/// case Error(): {
|
||||||
|
/// print(result.error);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
sealed class Result<T> {
|
||||||
|
const Result();
|
||||||
|
|
||||||
|
/// Creates a successful [Result], completed with the specified [value].
|
||||||
|
const factory Result.ok(T value) = Ok._;
|
||||||
|
|
||||||
|
/// Creates an error [Result], completed with the specified [error].
|
||||||
|
const factory Result.error(Exception error) = Error._;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A successful [Result] with a returned [value].
|
||||||
|
final class Ok<T> extends Result<T> {
|
||||||
|
const Ok._(this.value);
|
||||||
|
|
||||||
|
/// The returned value of this result.
|
||||||
|
final T value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Result<$T>.ok($value)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error [Result] with a resulting [error].
|
||||||
|
final class Error<T> extends Result<T> {
|
||||||
|
const Error._(this.error);
|
||||||
|
|
||||||
|
/// The resulting error of this result.
|
||||||
|
final Exception error;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'Result<$T>.error($error)';
|
||||||
|
}
|
Loading…
Reference in a new issue