feat: color a site from its address, and offer a failed web page to the system browser
This commit is contained in:
parent
56db479df0
commit
9d9f09ebc7
24 changed files with 597 additions and 25 deletions
|
|
@ -1,5 +1,8 @@
|
|||
import 'dart:io' show Process;
|
||||
|
||||
import 'package:flutter/foundation.dart'
|
||||
show defaultTargetPlatform, TargetPlatform;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart' show ScrollDirection;
|
||||
import 'package:flutter/services.dart' show LogicalKeyboardKey;
|
||||
|
|
@ -114,6 +117,7 @@ class _ReaderScreenState extends State<ReaderScreen> {
|
|||
pageVariant: page.variant,
|
||||
readerVariant: deps.settings.variant.value,
|
||||
dark: Theme.of(context).brightness == Brightness.dark,
|
||||
url: page.url,
|
||||
).background;
|
||||
|
||||
// The 40em column plus its padding: swipes are accepted
|
||||
|
|
@ -235,6 +239,7 @@ class _ReaderScreenState extends State<ReaderScreen> {
|
|||
pageVariant: page.variant,
|
||||
readerVariant: variant,
|
||||
dark: Theme.of(context).brightness == Brightness.dark,
|
||||
url: page.url,
|
||||
);
|
||||
return MewsPageView(
|
||||
key: ValueKey(page.url),
|
||||
|
|
@ -263,6 +268,7 @@ class _ReaderScreenState extends State<ReaderScreen> {
|
|||
pageVariant: page.variant,
|
||||
readerVariant: settings.variant.value,
|
||||
dark: Theme.of(context).brightness == Brightness.dark,
|
||||
url: page.url,
|
||||
);
|
||||
return ColoredBox(
|
||||
color: palette.background,
|
||||
|
|
@ -389,10 +395,46 @@ class _ReaderScreenState extends State<ReaderScreen> {
|
|||
);
|
||||
}
|
||||
|
||||
/// Hands [url] to the system's web browser. The reader does not watch
|
||||
/// what happens to it there, and a system with no browser answers nothing
|
||||
/// rather than failing here.
|
||||
///
|
||||
/// The launcher asks GIO on Linux, which can fail to see the session's
|
||||
/// browser from the environment the app runs in, and a binary built before
|
||||
/// the launcher was added answers not at all; in both cases xdg-open asks
|
||||
/// the session directly.
|
||||
Future<void> _openOutside(String url) async {
|
||||
final uri = Uri.tryParse(url);
|
||||
if (uri == null) return;
|
||||
|
||||
var opened = false;
|
||||
try {
|
||||
opened = await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} on Exception {
|
||||
// No answer; the fallback below asks the session itself.
|
||||
}
|
||||
if (opened) return;
|
||||
|
||||
if (defaultTargetPlatform == TargetPlatform.linux) {
|
||||
final result = await Process.run('xdg-open', [url]);
|
||||
// A missing xdg-open or a session without a browser answers with an
|
||||
// error; nothing more to do but stay where we are.
|
||||
if (result.exitCode != 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _errorPage(BuildContext context, String? brokenSource) {
|
||||
final strings = AppScope.of(context).strings;
|
||||
final deps = AppScope.of(context).deps;
|
||||
|
||||
// A web address can be shown by the system's browser, so a page that
|
||||
// will not load here can leave; a protocol page has nowhere else to go,
|
||||
// so only trying again is offered there.
|
||||
final failed = deps.browser.currentAddress;
|
||||
final failedScheme = Uri.tryParse(failed)?.scheme;
|
||||
final canOpenOutside =
|
||||
brokenSource == null && (failedScheme == 'http' || failedScheme == 'https');
|
||||
|
||||
Widget content;
|
||||
if (brokenSource == null) {
|
||||
content = Column(
|
||||
|
|
@ -404,6 +446,13 @@ class _ReaderScreenState extends State<ReaderScreen> {
|
|||
onPressed: () => deps.browser.reload(),
|
||||
child: Text(strings.t('error-try-again')),
|
||||
),
|
||||
if (canOpenOutside) ...[
|
||||
const SizedBox(height: 8),
|
||||
OutlinedButton(
|
||||
onPressed: () => _openOutside(failed),
|
||||
child: Text(strings.t('error-open-in-browser')),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
} else if (_showBrokenText) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue