import 'package:flutter/material.dart'; import 'package:gophershy/gopherlib.dart'; import 'package:gophershy/gopher_widgets.dart'; class _GopherBrowserState extends State { // TODO: when is this updated? how is the widget.initialUrl at play? // TODO: We must have button: Menu! to attempt to render any text file as menu // Because when we visit from direct url we don't know what file type we get // Other detection methods could be applied later String currentUrl = "gopher://treebrary.org"; // Directory listing doesn't have to end with / so we can never // be sure whether we're visiting menu or not. // When true, we try to parse anything as menu bool forceMenu = false; void gotoUrl(String link) { if (link == currentUrl) return; setState(() { print("prev: $currentUrl Submitted: $link"); currentUrl = link; }); } @override Widget build(BuildContext context) { print("GopherBrowseState: $currentUrl"); return Column( children: [ TextField(onSubmitted: gotoUrl), Expanded( child: GopherLoader( key: ValueKey(currentUrl), forceMenu: forceMenu, parsedGopherItem: ParsedGopherItem.parseUrl(currentUrl), )), ], ); } } class GopherBrowser extends StatefulWidget { final String initialUrl; const GopherBrowser({super.key, required this.initialUrl}); @override State createState() => _GopherBrowserState(); } class _GopherLoaderState extends State { Future? _data; @override void initState() { super.initState(); _data = widget.parsedGopherItem.load(forceMenu: widget.forceMenu); print("Reiniterd"); } @override void didChangeDependencies() { super.didChangeDependencies(); print("did:change: _data $_data"); setState(() { _data = widget.parsedGopherItem.load(forceMenu: widget.forceMenu); }); print('didChangeDependencies, mounted: ${1} done? '); print("$_data"); } void goToNext(ParsedGopherItem item) { setState(() { print("requesting view of: ${item.url} ${item.documentType}"); _data = item.load(forceMenu: false); }); } @override Widget build(BuildContext context) { return Center( child: FutureBuilder( future: _data, builder: (cont, snap) { print("${snap.connectionState}"); if (snap.connectionState != ConnectionState.done) { return const CircularProgressIndicator(); } else { if (snap.hasData) { print("data & doctype: ${snap.data!}, ${snap.data!.parsed.documentType}, "); return switch (snap.data!.parsed.documentType) { DocumentType.TextFile => GopherText(snap.data!), DocumentType.Directory => GopherDirectory( parsedDirectory: snap.data!, onItemClick: goToNext, ), _ => Container(color: Colors.yellow), }; } else { return const Text("Errored"); } } })); } } class GopherLoader extends StatefulWidget { final ParsedGopherItem parsedGopherItem; final bool? forceMenu; const GopherLoader( {super.key, required this.parsedGopherItem, this.forceMenu}); @override State createState() => _GopherLoaderState(); } class MenuItem extends StatelessWidget { static const Map _iconMap = { DocumentType.TextFile: Icons.short_text, DocumentType.Directory: Icons.folder, DocumentType.CSO: Icons.contact_page, DocumentType.ErrorCode: Icons.error, DocumentType.BinHex: Icons.precision_manufacturing_sharp, DocumentType.DosBinary: Icons.precision_manufacturing_rounded, DocumentType.Uuencoded: Icons.precision_manufacturing_outlined, DocumentType.Search: Icons.search_rounded, DocumentType.Telnet: Icons.smart_screen_sharp, DocumentType.Telnet3270: Icons.smart_screen_sharp, DocumentType.Binary: Icons.file_download, DocumentType.MirrorOrAlternate: Icons.content_copy, DocumentType.Gif: Icons.animation, DocumentType.Image: Icons.image, DocumentType.Bitmap: Icons.picture_as_pdf, DocumentType.Movie: Icons.local_movies, DocumentType.Soundfile: Icons.music_note, DocumentType.Doc: Icons.document_scanner, DocumentType.Html: Icons.html, DocumentType.Informational: Icons.info, DocumentType.PngImage: Icons.hide_image_sharp, DocumentType.RichTextDocument: Icons.format_color_text, DocumentType.SoundFile: Icons.library_music, DocumentType.Pdf: Icons.picture_as_pdf, DocumentType.Xml: Icons.html_rounded, DocumentType.Unknown: Icons.question_mark, }; IconData _getIcon(DocumentType forWhat) { return _iconMap[forWhat] ?? Icons.question_mark_sharp; } final ParsedGopherItem item; const MenuItem(this.item, {super.key}); void _itemTap(BuildContext cont) { Navigator.push(cont, MaterialPageRoute(builder: (cont) { if (item.documentType == DocumentType.Directory) { return const Text("it was a directory"); } else { return Container(); } })); } @override Widget build(BuildContext context) { // TODO: Something something virtual item here as well if (item.documentType == DocumentType.Unknown) { return Text(item.name ?? "?"); } // Put it into GestureDetector and on click open new route loading given item return GestureDetector( onTap: () => _itemTap(context), child: Row( children: [ Icon(_getIcon(item.documentType)), Column( children: [ Text(item.name ?? ""), ], ), ], ), ); } }