Get Super basic navigation stack going
This commit is contained in:
parent
887ef4cfd4
commit
dfc2de6e33
2 changed files with 108 additions and 55 deletions
24
features.org
24
features.org
|
@ -1,13 +1,17 @@
|
|||
- [ ] Most important features [0%]
|
||||
- [ ] Navigation stack with loaded items and urls
|
||||
- Capture the back key
|
||||
- Add buttons to go back & forth
|
||||
- Figure out a way to exit with back arrow
|
||||
- Maybe go with back arrow until the begginging of navigation stack and then double click?
|
||||
- [ ] [[https://github.com/llfbandit/app_links/blob/master/doc/README_android.md][Register to handle]] ~gopher://~ protocol
|
||||
- [ ] Line wrap togglable for text files and menus
|
||||
* Features non exhaustive list of TODOs
|
||||
|
||||
Some todos collected from source code, sorted roughly in the order of importance
|
||||
- [-] *Most important features* [0%]
|
||||
- [-] Navigation stack with loaded items and urls [1/3]
|
||||
- [X] Capture the back key
|
||||
- [ ] Add buttons to go back & forth
|
||||
- [ ] Show toast at the end of history and exit after double click on back arrow
|
||||
- [ ] Line wrap togglable for text files and menus [0/3]
|
||||
- [ ] Add toolbar with disable wrap button
|
||||
- [ ] Menu should be nonwrapping by default
|
||||
- [ ] Add option to wrap only filenames and not info items as they may be just decoration
|
||||
- [ ] [[https://github.com/llfbandit/app_links/blob/master/doc/README_android.md][Register to handle]] ~gopher://~ protocol
|
||||
- [ ] Keep toolbar url up to date
|
||||
- [ ] Fix line reading from socket
|
||||
- [ ] Bookmarks
|
||||
- [ ] Picture view with option to save to file
|
||||
|
@ -15,7 +19,9 @@
|
|||
- [ ] Option to "Open in app" for all files that we don't know how to handle (pdf, exec binaries, sound files)
|
||||
- [ ] Homepage or custom homepage
|
||||
- [ ] Working user input
|
||||
- [ ] Nice to haves
|
||||
- [ ] *Configuration options*
|
||||
- [ ] Option to select whether back arrow goes Up directory tree ro back in navigation stack
|
||||
- [ ] *Nice to haves* [0%]
|
||||
- [ ] Icon
|
||||
- [ ] Preferences for navigation stack depth (both loaded & url stacks)
|
||||
- [ ] Preferences for
|
||||
|
|
|
@ -7,16 +7,31 @@ class _GopherBrowserState extends State<GopherBrowser> {
|
|||
// 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
|
||||
// This may not be the most common use case so maybe hide it in some hayburger menu
|
||||
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;
|
||||
|
||||
/// Only links to session history, will be much bigger than [_loadedStack]
|
||||
// Probably remove from here
|
||||
final List<ParsedGopherItem> _urlStack = List<ParsedGopherItem>.empty(growable: true);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_currentItem = ParsedGopherItem.parseUrl(widget.initialUrl);
|
||||
}
|
||||
|
||||
late ParsedGopherItem _currentItem;
|
||||
void gotoUrl(String link) {
|
||||
print("GoTo: $link from: $currentUrl");
|
||||
if (link == currentUrl) return;
|
||||
setState(() {
|
||||
print("prev: $currentUrl Submitted: $link");
|
||||
print("prev: Submitted: $link");
|
||||
_currentItem = ParsedGopherItem.parseUrl(link);
|
||||
_urlStack.add(_currentItem);
|
||||
currentUrl = link;
|
||||
});
|
||||
}
|
||||
|
@ -24,17 +39,21 @@ class _GopherBrowserState extends State<GopherBrowser> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
print("GopherBrowseState: $currentUrl");
|
||||
return Column(
|
||||
children: [
|
||||
TextField(onSubmitted: gotoUrl),
|
||||
Expanded(
|
||||
return Builder(builder: (context) {
|
||||
return Column(
|
||||
children: [
|
||||
TextField(
|
||||
onSubmitted: gotoUrl,
|
||||
),
|
||||
Expanded(
|
||||
child: GopherLoader(
|
||||
key: ValueKey(currentUrl),
|
||||
forceMenu: forceMenu,
|
||||
parsedGopherItem: ParsedGopherItem.parseUrl(currentUrl),
|
||||
)),
|
||||
],
|
||||
);
|
||||
key: ValueKey(currentUrl),
|
||||
forceMenu: forceMenu,
|
||||
parsedGopherItem: _currentItem,
|
||||
)),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,57 +68,85 @@ class GopherBrowser extends StatefulWidget {
|
|||
class _GopherLoaderState extends State<GopherLoader> {
|
||||
Future<LoadedGopherItem>? _data;
|
||||
|
||||
final List<LoadedGopherItem> _loadedHistory =
|
||||
List<LoadedGopherItem>.empty(growable: true);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_data = widget.parsedGopherItem.load(forceMenu: widget.forceMenu);
|
||||
print("Reiniterd");
|
||||
_data = widget.parsedGopherItem.load(forceMenu: widget.forceMenu).then(
|
||||
(value) {
|
||||
print("Pushed beacuse of initState");
|
||||
return _onLoadFinished(value);
|
||||
},
|
||||
);
|
||||
print("Reinitred GopherLoaderState");
|
||||
}
|
||||
|
||||
@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");
|
||||
LoadedGopherItem _onLoadFinished(LoadedGopherItem data) {
|
||||
_loadedHistory.add(data);
|
||||
print("Added to histor: ${_loadedHistory.length}");
|
||||
return data;
|
||||
}
|
||||
|
||||
void goToNext(ParsedGopherItem item) {
|
||||
void _goToNext(ParsedGopherItem item, {String? why}) {
|
||||
print("Going to next: $why");
|
||||
setState(() {
|
||||
print("requesting view of: ${item.url} ${item.documentType}");
|
||||
_data = item.load(forceMenu: false);
|
||||
_data = item.load(forceMenu: false).then(
|
||||
(value) {
|
||||
print("Pushed beacuse of gotoNext");
|
||||
return _onLoadFinished(value);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _onBackButton(bool popable, object) {
|
||||
print("Gonna pop i guess");
|
||||
// TODO: toast if at the end of history, make time stamp and quit if pressed back button quickly again
|
||||
// TODO: Setting on whether back button goes up a directory or back in navigation stack -> may be the same but might not be
|
||||
if (_loadedHistory.length > 1) {
|
||||
_loadedHistory.removeLast();
|
||||
setState(() {
|
||||
_data = Future<LoadedGopherItem>.delayed(
|
||||
Duration.zero, () => _loadedHistory.last);
|
||||
});
|
||||
} else {
|
||||
// TODO: Toast here
|
||||
print("At the end of stack");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: FutureBuilder<LoadedGopherItem>(
|
||||
future: _data,
|
||||
builder: (cont, snap) {
|
||||
print("${snap.connectionState}");
|
||||
if (snap.connectionState != ConnectionState.done) {
|
||||
return const CircularProgressIndicator();
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: _onBackButton,
|
||||
child: FutureBuilder<LoadedGopherItem>(
|
||||
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 {
|
||||
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");
|
||||
}
|
||||
return Text("Errored ${snap.error}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue