80 lines
2.3 KiB
Dart
80 lines
2.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:signals/signals_flutter.dart' show SignalBuilder;
|
|
|
|
import '../app.dart';
|
|
|
|
/// The single-field address bar at the top of the reader. Submitting navigates;
|
|
/// the field shows the current page's URL whenever the reader is not typing.
|
|
class AddressBar extends StatefulWidget {
|
|
const AddressBar({super.key});
|
|
|
|
@override
|
|
State<AddressBar> createState() => _AddressBarState();
|
|
}
|
|
|
|
class _AddressBarState extends State<AddressBar> {
|
|
final _controller = TextEditingController();
|
|
final _focus = FocusNode();
|
|
bool _focused = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_focus.addListener(() {
|
|
if (_focus.hasFocus != _focused) {
|
|
setState(() => _focused = _focus.hasFocus);
|
|
if (_focused) {
|
|
_controller.selection =
|
|
TextSelection(baseOffset: 0, extentOffset: _controller.text.length);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_focus.dispose();
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final deps = AppScope.of(context).deps;
|
|
final strings = AppScope.of(context).strings;
|
|
|
|
return SignalBuilder(builder: (context) {
|
|
final url = deps.browser.currentPage.value?.url;
|
|
if (url != null && !_focused) {
|
|
_controller.text = url;
|
|
}
|
|
return Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 8, 8, 4),
|
|
child: TextField(
|
|
controller: _controller,
|
|
focusNode: _focus,
|
|
autofocus: false,
|
|
keyboardType: TextInputType.url,
|
|
textInputAction: TextInputAction.go,
|
|
autocorrect: false,
|
|
enableSuggestions: false,
|
|
onSubmitted: (value) {
|
|
_focus.unfocus();
|
|
deps.browser.open(value);
|
|
},
|
|
decoration: InputDecoration(
|
|
hintText: strings.t('reader-address-placeholder'),
|
|
labelText: strings.t('reader-address-label'),
|
|
prefixIcon: IconButton(
|
|
icon: const Icon(Icons.refresh),
|
|
tooltip: strings.t('reader-reload'),
|
|
onPressed: () => deps.browser.reload(),
|
|
),
|
|
isDense: true,
|
|
border: const OutlineInputBorder(),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
}
|
|
}
|