import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:flutter_svg/svg.dart'; import 'package:mobile_nebula/components/SimplePage.dart'; import 'package:mobile_nebula/models/Site.dart'; import 'package:mobile_nebula/services/settings.dart'; import 'package:mobile_nebula/services/share.dart'; import 'package:mobile_nebula/services/utils.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; class SiteLogsScreen extends StatefulWidget { const SiteLogsScreen({Key? key, required this.site}) : super(key: key); final Site site; @override _SiteLogsScreenState createState() => _SiteLogsScreenState(); } class _SiteLogsScreenState extends State { String logs = ''; ScrollController controller = ScrollController(); RefreshController refreshController = RefreshController(initialRefresh: false); var settings = Settings(); @override void initState() { loadLogs(); super.initState(); } @override void dispose() { controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final dnIcon = Theme.of(context).brightness == Brightness.dark ? 'images/dn-logo-dark.svg' : 'images/dn-logo-light.svg'; final title = Row(children: [ widget.site.managed ? Padding(padding: EdgeInsets.only(right: 10), child: SvgPicture.asset(dnIcon, width: 12)) : Container(), Expanded(child: Text(widget.site.name, style: TextStyle(fontWeight: FontWeight.bold))) ]); return SimplePage( title: title, scrollable: SimpleScrollable.both, scrollController: controller, onRefresh: () async { await loadLogs(); refreshController.refreshCompleted(); }, onLoading: () async { await loadLogs(); refreshController.loadComplete(); }, refreshController: refreshController, child: Container( padding: EdgeInsets.all(5), constraints: logBoxConstraints(context), child: SelectableText(logs.trim(), style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14))), bottomBar: _buildBottomBar(), ); } Widget _buildBottomBar() { var borderSide = BorderSide( color: CupertinoColors.separator, style: BorderStyle.solid, width: 0.0, ); var padding = Platform.isAndroid ? EdgeInsets.fromLTRB(0, 20, 0, 30) : EdgeInsets.all(10); return Container( decoration: BoxDecoration( border: Border(top: borderSide), ), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded(child: Builder(builder: (BuildContext context) { return PlatformIconButton( padding: padding, icon: Icon(context.platformIcons.share, size: 30), onPressed: () { Share.shareFile(context, title: '${widget.site.name} logs', filePath: widget.site.logFile, filename: '${widget.site.name}.log'); }, ); })), Expanded( child: PlatformIconButton( padding: padding, icon: Icon(context.platformIcons.downArrow, size: 30), onPressed: () async { controller.animateTo(controller.position.maxScrollExtent, duration: const Duration(milliseconds: 500), curve: Curves.linearToEaseOut); }, )), ])); } 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) { if (settings.logWrap) { return BoxConstraints(maxWidth: MediaQuery.of(context).size.width); } else { return BoxConstraints(minWidth: MediaQuery.of(context).size.width); } } }