Skip to content

Commit

Permalink
Handle Hacker News links routing in-app
Browse files Browse the repository at this point in the history
  • Loading branch information
Mosc committed Dec 11, 2023
1 parent 108215a commit 7d78474
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 22 deletions.
3 changes: 2 additions & 1 deletion lib/auth/cubit/auth_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:glider/common/extensions/bloc_base_extension.dart';
import 'package:glider_domain/glider_domain.dart';

Expand All @@ -22,7 +23,7 @@ class AuthCubit extends Cubit<AuthState> {
}

Future<void> login() async {
final userCookieUrl = WebUri('https://news.ycombinator.com');
final userCookieUrl = WebUri.uri(AppUris.hackerNewsUri);
const userCookieName = 'user';
final userCookie = await _cookieManager.getCookie(
url: userCookieUrl,
Expand Down
6 changes: 5 additions & 1 deletion lib/auth/view/auth_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:glider/app/container/app_container.dart';
import 'package:glider/app/models/app_route.dart';
import 'package:glider/auth/cubit/auth_cubit.dart';
import 'package:glider/common/constants/app_spacing.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:glider/common/extensions/uri_extension.dart';
import 'package:glider/common/extensions/widget_list_extension.dart';
import 'package:glider/l10n/extensions/app_localizations_extension.dart';
Expand Down Expand Up @@ -118,7 +119,7 @@ class _AuthPageState extends State<AuthPage> {
),
urlRequest: URLRequest(
url: WebUri(
Uri.https('news.ycombinator.com', 'login').toString(),
AppUris.hackerNewsUri.replace(path: 'login').toString(),
),
),
),
Expand Down Expand Up @@ -165,6 +166,7 @@ class _AuthBody extends StatelessWidget {
'github.com',
'Mosc/Glider/blob/master/PRIVACY.md',
).tryLaunch(
context,
useInAppBrowser: _settingsCubit.state.useInAppBrowser,
),
child: Text(context.l10n.privacyPolicy),
Expand All @@ -174,6 +176,7 @@ class _AuthBody extends StatelessWidget {
'www.ycombinator.com',
'legal',
).replace(fragment: 'privacy').tryLaunch(
context,
useInAppBrowser: _settingsCubit.state.useInAppBrowser,
),
child: Text(context.l10n.privacyPolicyYc),
Expand All @@ -183,6 +186,7 @@ class _AuthBody extends StatelessWidget {
'www.ycombinator.com',
'legal',
).replace(fragment: 'tou').tryLaunch(
context,
useInAppBrowser: _settingsCubit.state.useInAppBrowser,
),
child: Text(context.l10n.termsOfUseYc),
Expand Down
5 changes: 5 additions & 0 deletions lib/common/constants/app_uris.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
abstract final class AppUris {
static final hackerNewsUri = Uri.https('news.ycombinator.com');

static final projectUri = Uri.https('github.com', 'Mosc/Glider');
}
16 changes: 15 additions & 1 deletion lib/common/extensions/uri_extension.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:go_router/go_router.dart';
import 'package:url_launcher/url_launcher.dart';

extension UriExtension on Uri {
Future<bool> tryLaunch({String? title, required bool useInAppBrowser}) async {
Future<bool> tryLaunch(
BuildContext context, {
String? title,
required bool useInAppBrowser,
}) async {
if (authority == AppUris.hackerNewsUri.authority) {
unawaited(context.push(toString()));
return true;
}

if (await canLaunchUrl(this)) {
if (await supportsLaunchMode(LaunchMode.externalNonBrowserApplication)) {
final success = await launchUrl(
Expand Down
1 change: 1 addition & 0 deletions lib/common/widgets/hacker_news_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class HackerNewsText extends StatelessWidget {
onTapLink: (text, href, title) async {
if (href != null) {
await Uri.tryParse(href)?.tryLaunch(
context,
title: title,
useInAppBrowser: useInAppBrowser,
);
Expand Down
8 changes: 4 additions & 4 deletions lib/item/models/item_value.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:glider/auth/cubit/auth_cubit.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:glider/common/interfaces/menu_item.dart';
import 'package:glider/item/cubit/item_cubit.dart';
import 'package:glider/l10n/extensions/app_localizations_extension.dart';
Expand Down Expand Up @@ -53,10 +54,9 @@ enum ItemValue implements MenuItem<ItemState> {
ItemValue.title => item?.title,
ItemValue.link => item?.url.toString(),
ItemValue.text => item?.text,
ItemValue.itemLink => Uri.https(
'news.ycombinator.com',
'item',
<String, String>{
ItemValue.itemLink => AppUris.hackerNewsUri.replace(
path: 'item',
queryParameters: <String, String>{
'id': itemCubit.itemId.toString(),
},
).toString(),
Expand Down
11 changes: 8 additions & 3 deletions lib/item/widgets/item_data_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,10 @@ class ItemDataTile extends StatelessWidget {
AnimatedVisibility(
visible: style == ItemStyle.overview,
child: InkWell(
onTap: () async =>
item.url!.tryLaunch(useInAppBrowser: useInAppBrowser),
onTap: () async => item.url!.tryLaunch(
context,
useInAppBrowser: useInAppBrowser,
),
// Explicitly override parent widget's long press.
onLongPress: () {},
child: _ItemFavicon(
Expand Down Expand Up @@ -359,7 +361,10 @@ class ItemDataTile extends StatelessWidget {
),
if (item.url case final url?)
DecoratedCard.outlined(
onTap: () async => url.tryLaunch(useInAppBrowser: useInAppBrowser),
onTap: () async => url.tryLaunch(
context,
useInAppBrowser: useInAppBrowser,
),
// Explicitly override parent widget's long press.
onLongPress: () {},
child: Row(
Expand Down
19 changes: 11 additions & 8 deletions lib/settings/view/settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/material.dart' hide ThemeMode;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:glider/app/models/app_route.dart';
import 'package:glider/common/constants/app_spacing.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:glider/common/extensions/uri_extension.dart';
import 'package:glider/common/widgets/preview_card.dart';
import 'package:glider/item/models/item_style.dart';
Expand Down Expand Up @@ -64,16 +65,14 @@ class _SettingsBody extends StatelessWidget {
'Open Sans',
'Roboto',
];
static const String _authority = 'github.com';
static const String _basePath = 'Mosc/Glider';
static final Uri _privacyPolicyUrl =
Uri.https(_authority, '$_basePath/blob/master/PRIVACY.md');
static final Uri _privacyPolicyUrl = AppUris.projectUri
.replace(path: '${AppUris.projectUri.path}/blob/master/PRIVACY.md');
static const String _license = 'MIT';
static final Uri _licenseUrl =
Uri.https(_authority, '$_basePath/blob/master/LICENSE');
static final Uri _sourceCodeUrl = Uri.https('github.com', _basePath);
static final Uri _licenseUrl = AppUris.projectUri
.replace(path: '${AppUris.projectUri.path}/blob/master/LICENSE');
static final Uri _sourceCodeUrl = AppUris.projectUri;
static final Uri _issueTrackerUrl =
Uri.https(_authority, '$_basePath/issues');
AppUris.projectUri.replace(path: '${AppUris.projectUri.path}/issues');

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -332,6 +331,7 @@ class _SettingsBody extends StatelessWidget {
title: Text(context.l10n.privacyPolicy),
trailing: const Icon(Icons.open_in_new_outlined),
onTap: () => _privacyPolicyUrl.tryLaunch(
context,
useInAppBrowser: state.useInAppBrowser,
),
),
Expand All @@ -340,6 +340,7 @@ class _SettingsBody extends StatelessWidget {
subtitle: const Text(_license),
trailing: const Icon(Icons.open_in_new_outlined),
onTap: () => _licenseUrl.tryLaunch(
context,
useInAppBrowser: state.useInAppBrowser,
),
),
Expand All @@ -348,6 +349,7 @@ class _SettingsBody extends StatelessWidget {
subtitle: Text(_sourceCodeUrl.toString()),
trailing: const Icon(Icons.open_in_new_outlined),
onTap: () => _sourceCodeUrl.tryLaunch(
context,
useInAppBrowser: state.useInAppBrowser,
),
),
Expand All @@ -356,6 +358,7 @@ class _SettingsBody extends StatelessWidget {
subtitle: Text(_issueTrackerUrl.toString()),
trailing: const Icon(Icons.open_in_new_outlined),
onTap: () => _issueTrackerUrl.tryLaunch(
context,
useInAppBrowser: state.useInAppBrowser,
),
),
Expand Down
8 changes: 4 additions & 4 deletions lib/user/models/user_value.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:glider/auth/cubit/auth_cubit.dart';
import 'package:glider/common/constants/app_uris.dart';
import 'package:glider/common/interfaces/menu_item.dart';
import 'package:glider/l10n/extensions/app_localizations_extension.dart';
import 'package:glider/settings/cubit/settings_cubit.dart';
Expand Down Expand Up @@ -48,10 +49,9 @@ enum UserValue implements MenuItem<UserState> {
return switch (this) {
UserValue.username => userCubit.username,
UserValue.about => user?.about,
UserValue.userLink => Uri.https(
'news.ycombinator.com',
'user',
<String, String>{
UserValue.userLink => AppUris.hackerNewsUri.replace(
path: 'user',
queryParameters: <String, String>{
'id': userCubit.username,
},
).toString(),
Expand Down

0 comments on commit 7d78474

Please sign in to comment.