Improved tablet webview
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
/// Locales: 2
|
/// Locales: 2
|
||||||
/// Strings: 350 (175 per locale)
|
/// Strings: 350 (175 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2024-02-28 at 19:46 UTC
|
/// Built on 2024-02-29 at 10:47 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'package:linkdy/config/options.dart';
|
import 'package:linkdy/config/options.dart';
|
||||||
import 'package:linkdy/constants/enums.dart';
|
import 'package:linkdy/constants/enums.dart';
|
||||||
import 'package:linkdy/models/data/bookmarks.dart';
|
import 'package:linkdy/models/data/bookmarks.dart';
|
||||||
@@ -11,6 +13,7 @@ class BookmarksModel {
|
|||||||
int maxNumber;
|
int maxNumber;
|
||||||
ReadStatus readStatus;
|
ReadStatus readStatus;
|
||||||
Bookmark? selectedBookmark;
|
Bookmark? selectedBookmark;
|
||||||
|
final GoRouter webViewRouter;
|
||||||
|
|
||||||
BookmarksModel({
|
BookmarksModel({
|
||||||
this.currentPage = 0,
|
this.currentPage = 0,
|
||||||
@@ -21,5 +24,6 @@ class BookmarksModel {
|
|||||||
this.maxNumber = 0,
|
this.maxNumber = 0,
|
||||||
this.readStatus = ReadStatus.all,
|
this.readStatus = ReadStatus.all,
|
||||||
this.selectedBookmark,
|
this.selectedBookmark,
|
||||||
|
required this.webViewRouter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'package:linkdy/config/options.dart';
|
import 'package:linkdy/config/options.dart';
|
||||||
import 'package:linkdy/constants/enums.dart';
|
import 'package:linkdy/constants/enums.dart';
|
||||||
@@ -14,6 +15,7 @@ class SearchBookmarksModel {
|
|||||||
bool loadingMore;
|
bool loadingMore;
|
||||||
int maxNumber;
|
int maxNumber;
|
||||||
Bookmark? selectedBookmark;
|
Bookmark? selectedBookmark;
|
||||||
|
final GoRouter webViewRouter;
|
||||||
|
|
||||||
SearchBookmarksModel({
|
SearchBookmarksModel({
|
||||||
required this.searchController,
|
required this.searchController,
|
||||||
@@ -25,5 +27,6 @@ class SearchBookmarksModel {
|
|||||||
this.loadingMore = false,
|
this.loadingMore = false,
|
||||||
this.maxNumber = 0,
|
this.maxNumber = 0,
|
||||||
this.selectedBookmark,
|
this.selectedBookmark,
|
||||||
|
required this.webViewRouter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/screens/webview/ui/webview.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/model/bookmarks.model.dart';
|
import 'package:linkdy/screens/bookmarks/model/bookmarks.model.dart';
|
||||||
@@ -59,12 +62,29 @@ FutureOr<void> bookmarksRequestLoadMore(BookmarksRequestLoadMoreRef ref) async {
|
|||||||
ref.read(bookmarksProvider.notifier).setLoadingMore(false);
|
ref.read(bookmarksProvider.notifier).setLoadingMore(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _webViewRoute = "wb";
|
||||||
|
const _webViewRoutePath = "/wb";
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class Bookmarks extends _$Bookmarks {
|
class Bookmarks extends _$Bookmarks {
|
||||||
@override
|
@override
|
||||||
BookmarksModel build() {
|
BookmarksModel build() {
|
||||||
final model = BookmarksModel(
|
final model = BookmarksModel(
|
||||||
bookmarks: [],
|
bookmarks: [],
|
||||||
|
webViewRouter: GoRouter(
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: "/",
|
||||||
|
builder: (context, state) => const SizedBox(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: _webViewRoute,
|
||||||
|
builder: (context, state) => WebViewScreen(bookmark: state.extra as Bookmark),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
ref.read(bookmarksRequestProvider(model.readStatus, model.limit));
|
ref.read(bookmarksRequestProvider(model.readStatus, model.limit));
|
||||||
return model;
|
return model;
|
||||||
@@ -98,11 +118,27 @@ class Bookmarks extends _$Bookmarks {
|
|||||||
ref.notifyListeners();
|
ref.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pushRoute(String path, bool splitMode) {
|
||||||
|
if (splitMode == true && state.webViewRouter.canPop()) {
|
||||||
|
state.selectedBookmark = null;
|
||||||
|
ref.notifyListeners();
|
||||||
|
state.webViewRouter.pop();
|
||||||
|
}
|
||||||
|
ref.read(routerProvider).push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearSelectedBookmark() {
|
||||||
|
state.selectedBookmark = null;
|
||||||
|
ref.notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
void selectBookmark(Bookmark bookmark, double width) {
|
void selectBookmark(Bookmark bookmark, double width) {
|
||||||
if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
|
if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
|
||||||
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
||||||
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
||||||
openUrl(bookmark.url!);
|
openUrl(bookmark.url!);
|
||||||
|
} else if (bookmark != state.selectedBookmark) {
|
||||||
|
state.webViewRouter.go(_webViewRoutePath, extra: bookmark);
|
||||||
}
|
}
|
||||||
state.selectedBookmark = bookmark;
|
state.selectedBookmark = bookmark;
|
||||||
ref.notifyListeners();
|
ref.notifyListeners();
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ final bookmarksRequestLoadMoreProvider =
|
|||||||
);
|
);
|
||||||
|
|
||||||
typedef BookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef<void>;
|
typedef BookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef<void>;
|
||||||
String _$bookmarksHash() => r'80e94e586950b9072f229958f98c88069086d7ab';
|
String _$bookmarksHash() => r'84c91bf9112343e4680040bfe25b5e17fb2f92d2';
|
||||||
|
|
||||||
/// See also [Bookmarks].
|
/// See also [Bookmarks].
|
||||||
@ProviderFor(Bookmarks)
|
@ProviderFor(Bookmarks)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/screens/webview/ui/webview.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
|
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
||||||
@@ -63,6 +65,9 @@ FutureOr<void> fetchSearchBookmarksLoadMore(FetchSearchBookmarksLoadMoreRef ref)
|
|||||||
ref.read(searchBookmarksProvider.notifier).setLoadingMore(false);
|
ref.read(searchBookmarksProvider.notifier).setLoadingMore(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _webViewRoute = "wb";
|
||||||
|
const _webViewRoutePath = "/wb";
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class SearchBookmarks extends _$SearchBookmarks {
|
class SearchBookmarks extends _$SearchBookmarks {
|
||||||
@override
|
@override
|
||||||
@@ -70,6 +75,20 @@ class SearchBookmarks extends _$SearchBookmarks {
|
|||||||
final model = SearchBookmarksModel(
|
final model = SearchBookmarksModel(
|
||||||
searchController: TextEditingController(),
|
searchController: TextEditingController(),
|
||||||
bookmarks: [],
|
bookmarks: [],
|
||||||
|
webViewRouter: GoRouter(
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: "/",
|
||||||
|
builder: (context, state) => const SizedBox(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: _webViewRoute,
|
||||||
|
builder: (context, state) => WebViewScreen(bookmark: state.extra as Bookmark),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
ref.read(fetchSearchBookmarksProvider(model.limit));
|
ref.read(fetchSearchBookmarksProvider(model.limit));
|
||||||
return model;
|
return model;
|
||||||
@@ -109,6 +128,8 @@ class SearchBookmarks extends _$SearchBookmarks {
|
|||||||
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
||||||
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
||||||
openUrl(bookmark.url!);
|
openUrl(bookmark.url!);
|
||||||
|
} else if (bookmark != state.selectedBookmark) {
|
||||||
|
state.webViewRouter.go(_webViewRoutePath, extra: bookmark);
|
||||||
}
|
}
|
||||||
state.selectedBookmark = bookmark;
|
state.selectedBookmark = bookmark;
|
||||||
ref.notifyListeners();
|
ref.notifyListeners();
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ final fetchSearchBookmarksLoadMoreProvider =
|
|||||||
);
|
);
|
||||||
|
|
||||||
typedef FetchSearchBookmarksLoadMoreRef = AutoDisposeFutureProviderRef<void>;
|
typedef FetchSearchBookmarksLoadMoreRef = AutoDisposeFutureProviderRef<void>;
|
||||||
String _$searchBookmarksHash() => r'3daf460b8389e8bcf8498c4bdf3935e88f4ce156';
|
String _$searchBookmarksHash() => r'5ebbd8dbfe705cbca9552fc60d251372c771d738';
|
||||||
|
|
||||||
/// See also [SearchBookmarks].
|
/// See also [SearchBookmarks].
|
||||||
@ProviderFor(SearchBookmarks)
|
@ProviderFor(SearchBookmarks)
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart';
|
|||||||
import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart';
|
import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart';
|
import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/ui/search_bookmarks.dart';
|
import 'package:linkdy/screens/bookmarks/ui/search_bookmarks.dart';
|
||||||
import 'package:linkdy/screens/webview/ui/webview.dart';
|
|
||||||
import 'package:linkdy/widgets/circle_page_transition.dart';
|
import 'package:linkdy/widgets/circle_page_transition.dart';
|
||||||
import 'package:linkdy/widgets/error_screen.dart';
|
import 'package:linkdy/widgets/error_screen.dart';
|
||||||
import 'package:linkdy/widgets/no_data_screen.dart';
|
import 'package:linkdy/widgets/no_data_screen.dart';
|
||||||
|
|
||||||
import 'package:linkdy/config/sizes.dart';
|
import 'package:linkdy/config/sizes.dart';
|
||||||
import 'package:linkdy/constants/enums.dart';
|
import 'package:linkdy/constants/enums.dart';
|
||||||
import 'package:linkdy/providers/router.provider.dart';
|
|
||||||
import 'package:linkdy/router/paths.dart';
|
import 'package:linkdy/router/paths.dart';
|
||||||
import 'package:linkdy/constants/global_keys.dart';
|
import 'package:linkdy/constants/global_keys.dart';
|
||||||
import 'package:linkdy/i18n/strings.g.dart';
|
import 'package:linkdy/i18n/strings.g.dart';
|
||||||
|
import 'package:linkdy/widgets/system_overlay_style.dart';
|
||||||
|
|
||||||
final GlobalKey _searchButtonKey = GlobalKey();
|
final GlobalKey _searchButtonKey = GlobalKey();
|
||||||
|
final webviewBookmarksKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
class BookmarksScreen extends ConsumerWidget {
|
class BookmarksScreen extends ConsumerWidget {
|
||||||
const BookmarksScreen({super.key});
|
const BookmarksScreen({super.key});
|
||||||
@@ -35,16 +35,12 @@ class BookmarksScreen extends ConsumerWidget {
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const Expanded(flex: 2, child: _List(tabletMode: true)),
|
const Expanded(flex: 2, child: _List(tabletMode: true)),
|
||||||
if (ref.watch(bookmarksProvider).selectedBookmark != null)
|
Expanded(
|
||||||
Expanded(
|
flex: 3,
|
||||||
flex: 3,
|
child: Material(
|
||||||
child: WebViewScreen(bookmark: ref.watch(bookmarksProvider).selectedBookmark!),
|
child: Router.withConfig(config: ref.watch(bookmarksProvider).webViewRouter),
|
||||||
),
|
|
||||||
if (ref.watch(bookmarksProvider).selectedBookmark == null)
|
|
||||||
const Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: SizedBox(),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -71,6 +67,10 @@ class _List extends ConsumerWidget {
|
|||||||
|
|
||||||
void openSearchModal() {
|
void openSearchModal() {
|
||||||
if (_searchButtonKey.currentContext == null) return;
|
if (_searchButtonKey.currentContext == null) return;
|
||||||
|
if (tabletMode == true && ref.read(bookmarksProvider).webViewRouter.canPop()) {
|
||||||
|
ref.read(bookmarksProvider.notifier).clearSelectedBookmark();
|
||||||
|
ref.read(bookmarksProvider).webViewRouter.pop();
|
||||||
|
}
|
||||||
RenderBox box = _searchButtonKey.currentContext!.findRenderObject() as RenderBox;
|
RenderBox box = _searchButtonKey.currentContext!.findRenderObject() as RenderBox;
|
||||||
Offset position = box.localToGlobal(Offset.zero);
|
Offset position = box.localToGlobal(Offset.zero);
|
||||||
Navigator.of(context, rootNavigator: true).push(
|
Navigator.of(context, rootNavigator: true).push(
|
||||||
@@ -91,200 +91,204 @@ class _List extends ConsumerWidget {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return OverlayStyle(
|
||||||
body: NestedScrollView(
|
child: Scaffold(
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
body: NestedScrollView(
|
||||||
SliverOverlapAbsorber(
|
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
SliverOverlapAbsorber(
|
||||||
sliver: SliverAppBar.large(
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
pinned: true,
|
sliver: SliverAppBar.large(
|
||||||
floating: true,
|
pinned: true,
|
||||||
centerTitle: false,
|
floating: true,
|
||||||
forceElevated: innerBoxIsScrolled,
|
centerTitle: false,
|
||||||
title: Row(
|
forceElevated: innerBoxIsScrolled,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
title: Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
Text(t.bookmarks.bookmarks),
|
children: [
|
||||||
if (bookmarks.readStatus == ReadStatus.read || bookmarks.readStatus == ReadStatus.unread)
|
Text(t.bookmarks.bookmarks),
|
||||||
Container(
|
if (bookmarks.readStatus == ReadStatus.read || bookmarks.readStatus == ReadStatus.unread)
|
||||||
margin: const EdgeInsets.only(left: 8),
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
margin: const EdgeInsets.only(left: 8),
|
||||||
horizontal: 8,
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 4,
|
horizontal: 8,
|
||||||
),
|
vertical: 4,
|
||||||
decoration: BoxDecoration(
|
),
|
||||||
borderRadius: BorderRadius.circular(20),
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
child: Row(
|
),
|
||||||
children: [
|
child: Row(
|
||||||
Icon(
|
children: [
|
||||||
bookmarks.readStatus == ReadStatus.read
|
Icon(
|
||||||
? Icons.mark_email_read_rounded
|
bookmarks.readStatus == ReadStatus.read
|
||||||
: Icons.mark_as_unread_rounded,
|
? Icons.mark_email_read_rounded
|
||||||
size: 14,
|
: Icons.mark_as_unread_rounded,
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
size: 14,
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
bookmarks.readStatus == ReadStatus.read ? t.bookmarks.read : t.bookmarks.unread,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 4),
|
||||||
],
|
Text(
|
||||||
|
bookmarks.readStatus == ReadStatus.read ? t.bookmarks.read : t.bookmarks.unread,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
key: _searchButtonKey,
|
||||||
|
onPressed: openSearchModal,
|
||||||
|
icon: const Icon(Icons.search_rounded),
|
||||||
|
tooltip: t.bookmarks.search.searchBookmarks,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder: (context) => const VisualizationModal(),
|
||||||
|
isScrollControlled: true,
|
||||||
),
|
),
|
||||||
|
icon: const Icon(Icons.sort_rounded),
|
||||||
|
tooltip: t.bookmarks.filterSort,
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
|
itemBuilder: (context) => <PopupMenuEntry>[
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () =>
|
||||||
|
ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.archivedBookmarks, tabletMode),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.archive_rounded),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Text(t.bookmarks.archived),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () =>
|
||||||
|
ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.sharedBookmarks, tabletMode),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.share_rounded),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Text(t.bookmarks.shared),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const PopupMenuDivider(height: 1),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () => ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.tags, tabletMode),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.label_rounded),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Text(t.tags.tags),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const PopupMenuDivider(height: 1),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () => ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.settings, tabletMode),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.settings_rounded),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Text(t.settings.settings),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
key: _searchButtonKey,
|
|
||||||
onPressed: openSearchModal,
|
|
||||||
icon: const Icon(Icons.search_rounded),
|
|
||||||
tooltip: t.bookmarks.search.searchBookmarks,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
useRootNavigator: true,
|
|
||||||
builder: (context) => const VisualizationModal(),
|
|
||||||
isScrollControlled: true,
|
|
||||||
),
|
|
||||||
icon: const Icon(Icons.sort_rounded),
|
|
||||||
tooltip: t.bookmarks.filterSort,
|
|
||||||
),
|
|
||||||
PopupMenuButton(
|
|
||||||
itemBuilder: (context) => <PopupMenuEntry>[
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.archivedBookmarks),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.archive_rounded),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Text(t.bookmarks.archived),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.sharedBookmarks),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.share_rounded),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Text(t.bookmarks.shared),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const PopupMenuDivider(height: 1),
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.tags),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.label_rounded),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Text(t.tags.tags),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const PopupMenuDivider(height: 1),
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => ref.read(routerProvider).push(RoutesPaths.settings),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.settings_rounded),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Text(t.settings.settings),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
body: SafeArea(
|
||||||
body: SafeArea(
|
top: false,
|
||||||
top: false,
|
bottom: true,
|
||||||
bottom: true,
|
child: Builder(
|
||||||
child: Builder(
|
builder: (context) => RefreshIndicator(
|
||||||
builder: (context) => RefreshIndicator(
|
displacement: 120,
|
||||||
displacement: 120,
|
onRefresh: () => ref.read(bookmarksProvider.notifier).refresh(),
|
||||||
onRefresh: () => ref.read(bookmarksProvider.notifier).refresh(),
|
child: NotificationListener(
|
||||||
child: NotificationListener(
|
onNotification: scrollListener,
|
||||||
onNotification: scrollListener,
|
child: CustomScrollView(
|
||||||
child: CustomScrollView(
|
slivers: [
|
||||||
slivers: [
|
SliverOverlapInjector(
|
||||||
SliverOverlapInjector(
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
|
||||||
),
|
|
||||||
if (bookmarks.inialLoadStatus == LoadStatus.loading)
|
|
||||||
const SliverFillRemaining(
|
|
||||||
child: Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
),
|
||||||
if (bookmarks.inialLoadStatus == LoadStatus.error)
|
if (bookmarks.inialLoadStatus == LoadStatus.loading)
|
||||||
SliverFillRemaining(
|
const SliverFillRemaining(
|
||||||
child: ErrorScreen(
|
child: Center(child: CircularProgressIndicator()),
|
||||||
error: t.bookmarks.cannotLoadBookmarks,
|
|
||||||
),
|
),
|
||||||
),
|
if (bookmarks.inialLoadStatus == LoadStatus.error)
|
||||||
if (bookmarks.bookmarks.isEmpty)
|
SliverFillRemaining(
|
||||||
SliverFillRemaining(
|
child: ErrorScreen(
|
||||||
child: NoDataScreen(
|
error: t.bookmarks.cannotLoadBookmarks,
|
||||||
message: t.bookmarks.noBookmarksAdded,
|
),
|
||||||
),
|
),
|
||||||
),
|
if (bookmarks.bookmarks.isEmpty)
|
||||||
if (bookmarks.bookmarks.isNotEmpty)
|
SliverFillRemaining(
|
||||||
SlidableAutoCloseBehavior(
|
child: NoDataScreen(
|
||||||
child: SliverList.builder(
|
message: t.bookmarks.noBookmarksAdded,
|
||||||
itemCount: bookmarks.bookmarks.length + 1,
|
),
|
||||||
itemBuilder: (context, index) {
|
),
|
||||||
// index == bookmarks.value!.content!.results!.length -> itemCount + 1
|
if (bookmarks.bookmarks.isNotEmpty)
|
||||||
if (index == bookmarks.bookmarks.length) {
|
SlidableAutoCloseBehavior(
|
||||||
if (bookmarks.loadingMore) {
|
child: SliverList.builder(
|
||||||
return const SizedBox(
|
itemCount: bookmarks.bookmarks.length + 1,
|
||||||
height: 80,
|
itemBuilder: (context, index) {
|
||||||
child: Center(
|
// index == bookmarks.value!.content!.results!.length -> itemCount + 1
|
||||||
child: CircularProgressIndicator(),
|
if (index == bookmarks.bookmarks.length) {
|
||||||
),
|
if (bookmarks.loadingMore) {
|
||||||
);
|
return const SizedBox(
|
||||||
|
height: 80,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Bottom gap for FAB
|
||||||
|
return const SizedBox(height: 80);
|
||||||
}
|
}
|
||||||
// Bottom gap for FAB
|
return BookmarkItem(
|
||||||
return const SizedBox(height: 80);
|
bookmark: bookmarks.bookmarks[index],
|
||||||
}
|
onSelect: (b) => ref.read(bookmarksProvider.notifier).selectBookmark(b, width),
|
||||||
return BookmarkItem(
|
onReadUnread: ref.read(bookmarksProvider.notifier).markAsReadUnread,
|
||||||
bookmark: bookmarks.bookmarks[index],
|
onDelete: (bookmark) => showDialog(
|
||||||
onSelect: (b) => ref.read(bookmarksProvider.notifier).selectBookmark(b, width),
|
context: context,
|
||||||
onReadUnread: ref.read(bookmarksProvider.notifier).markAsReadUnread,
|
builder: (context) => DeleteBookmarkModal(
|
||||||
onDelete: (bookmark) => showDialog(
|
bookmark: bookmark,
|
||||||
context: context,
|
onDelete: ref.read(bookmarksProvider.notifier).deleteBookmark,
|
||||||
builder: (context) => DeleteBookmarkModal(
|
),
|
||||||
bookmark: bookmark,
|
|
||||||
onDelete: ref.read(bookmarksProvider.notifier).deleteBookmark,
|
|
||||||
),
|
),
|
||||||
),
|
onArchiveUnarchive: ref.read(bookmarksProvider.notifier).archiveUnarchive,
|
||||||
onArchiveUnarchive: ref.read(bookmarksProvider.notifier).archiveUnarchive,
|
onShareInternally: ref.read(bookmarksProvider.notifier).shareUnshare,
|
||||||
onShareInternally: ref.read(bookmarksProvider.notifier).shareUnshare,
|
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
|
||||||
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
|
selected: bookmarks.bookmarks[index] == bookmarks.selectedBookmark,
|
||||||
selected: bookmarks.bookmarks[index] == bookmarks.selectedBookmark,
|
tabletMode: tabletMode,
|
||||||
tabletMode: tabletMode,
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
floatingActionButton: FloatingActionButton(
|
||||||
floatingActionButton: FloatingActionButton(
|
onPressed: () => openBookmarkFormModal(context: context, width: width),
|
||||||
onPressed: () => openBookmarkFormModal(context: context, width: width),
|
child: const Icon(Icons.add_rounded),
|
||||||
child: const Icon(Icons.add_rounded),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:linkdy/screens/bookmarks/provider/search_bookmarks.provider.dart
|
|||||||
import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart';
|
import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart';
|
import 'package:linkdy/screens/bookmarks/ui/bookmark_item.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart';
|
import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart';
|
||||||
import 'package:linkdy/screens/webview/ui/webview.dart';
|
|
||||||
import 'package:linkdy/widgets/enter_search_term_screen.dart';
|
import 'package:linkdy/widgets/enter_search_term_screen.dart';
|
||||||
import 'package:linkdy/widgets/no_data_screen.dart';
|
import 'package:linkdy/widgets/no_data_screen.dart';
|
||||||
import 'package:linkdy/widgets/error_screen.dart';
|
import 'package:linkdy/widgets/error_screen.dart';
|
||||||
@@ -37,18 +36,13 @@ class SearchBookmarksModal extends ConsumerWidget {
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const Expanded(flex: 2, child: _List(tabletMode: true)),
|
const Expanded(flex: 2, child: _List(tabletMode: true)),
|
||||||
if (ref.watch(searchBookmarksProvider).selectedBookmark != null)
|
Expanded(
|
||||||
Expanded(
|
flex: 3,
|
||||||
flex: 3,
|
child: Material(
|
||||||
child: WebViewScreen(bookmark: ref.watch(searchBookmarksProvider).selectedBookmark!),
|
color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2),
|
||||||
),
|
child: Router.withConfig(config: ref.watch(searchBookmarksProvider).webViewRouter),
|
||||||
if (ref.watch(searchBookmarksProvider).selectedBookmark == null)
|
|
||||||
Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: Container(
|
|
||||||
color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'package:linkdy/config/options.dart';
|
import 'package:linkdy/config/options.dart';
|
||||||
import 'package:linkdy/constants/enums.dart';
|
import 'package:linkdy/constants/enums.dart';
|
||||||
import 'package:linkdy/models/data/bookmarks.dart';
|
import 'package:linkdy/models/data/bookmarks.dart';
|
||||||
@@ -14,6 +16,7 @@ class FilteredBookmarksModel {
|
|||||||
int maxNumber;
|
int maxNumber;
|
||||||
bool loadingMore;
|
bool loadingMore;
|
||||||
Bookmark? selectedBookmark;
|
Bookmark? selectedBookmark;
|
||||||
|
final GoRouter webViewRouter;
|
||||||
|
|
||||||
FilteredBookmarksModel({
|
FilteredBookmarksModel({
|
||||||
this.filteredBookmarksMode = FilteredBookmarksMode.shared,
|
this.filteredBookmarksMode = FilteredBookmarksMode.shared,
|
||||||
@@ -26,5 +29,6 @@ class FilteredBookmarksModel {
|
|||||||
this.maxNumber = 0,
|
this.maxNumber = 0,
|
||||||
this.loadingMore = false,
|
this.loadingMore = false,
|
||||||
this.selectedBookmark,
|
this.selectedBookmark,
|
||||||
|
required this.webViewRouter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/screens/webview/ui/webview.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
|
||||||
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
|
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
|
||||||
@@ -123,12 +126,29 @@ FutureOr<void> filteredBookmarksRequestLoadMore(TagBookmarksRequestLoadMoreRef r
|
|||||||
ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false);
|
ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _webViewRoute = "wb";
|
||||||
|
const _webViewRoutePath = "/wb";
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class FilteredBookmarks extends _$FilteredBookmarks {
|
class FilteredBookmarks extends _$FilteredBookmarks {
|
||||||
@override
|
@override
|
||||||
FilteredBookmarksModel build() {
|
FilteredBookmarksModel build() {
|
||||||
return FilteredBookmarksModel(
|
return FilteredBookmarksModel(
|
||||||
bookmarks: [],
|
bookmarks: [],
|
||||||
|
webViewRouter: GoRouter(
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: "/",
|
||||||
|
builder: (context, state) => const SizedBox(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: _webViewRoute,
|
||||||
|
builder: (context, state) => WebViewScreen(bookmark: state.extra as Bookmark),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +179,8 @@ class FilteredBookmarks extends _$FilteredBookmarks {
|
|||||||
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
|
||||||
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == false) {
|
||||||
openUrl(bookmark.url!);
|
openUrl(bookmark.url!);
|
||||||
|
} else if (bookmark != state.selectedBookmark) {
|
||||||
|
state.webViewRouter.go(_webViewRoutePath, extra: bookmark);
|
||||||
}
|
}
|
||||||
state.selectedBookmark = bookmark;
|
state.selectedBookmark = bookmark;
|
||||||
ref.notifyListeners();
|
ref.notifyListeners();
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ final filteredBookmarksRequestLoadMoreProvider =
|
|||||||
|
|
||||||
typedef FilteredBookmarksRequestLoadMoreRef
|
typedef FilteredBookmarksRequestLoadMoreRef
|
||||||
= AutoDisposeFutureProviderRef<void>;
|
= AutoDisposeFutureProviderRef<void>;
|
||||||
String _$filteredBookmarksHash() => r'584c9ee245200f653d43b10d807860dcbac68ff5';
|
String _$filteredBookmarksHash() => r'e58baf5c41c61233e76edea16830f1a47d6a645a';
|
||||||
|
|
||||||
/// See also [FilteredBookmarks].
|
/// See also [FilteredBookmarks].
|
||||||
@ProviderFor(FilteredBookmarks)
|
@ProviderFor(FilteredBookmarks)
|
||||||
|
|||||||
@@ -82,16 +82,12 @@ class FilteredBookmarksScreen extends HookConsumerWidget {
|
|||||||
tabletMode: true,
|
tabletMode: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (ref.watch(filteredBookmarksProvider).selectedBookmark != null)
|
Expanded(
|
||||||
Expanded(
|
flex: 3,
|
||||||
flex: 3,
|
child: Material(
|
||||||
child: WebViewScreen(bookmark: ref.watch(filteredBookmarksProvider).selectedBookmark!),
|
child: Router.withConfig(config: ref.watch(filteredBookmarksProvider).webViewRouter),
|
||||||
),
|
|
||||||
if (ref.watch(filteredBookmarksProvider).selectedBookmark == null)
|
|
||||||
const Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: SizedBox(),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,4 +46,9 @@ class WebView extends _$WebView {
|
|||||||
state.canGoForward = value;
|
state.canGoForward = value;
|
||||||
ref.notifyListeners();
|
ref.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadNewUrl(String url) {
|
||||||
|
ref.invalidateSelf();
|
||||||
|
state.webViewController.loadRequest(Uri.parse(url));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'webview.provider.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$webViewHash() => r'5b2504eb96acedfbc82e8c6747821db864221bee';
|
String _$webViewHash() => r'ae307e7a5014a44777bd6af7fd9cae7f96970610';
|
||||||
|
|
||||||
/// See also [WebView].
|
/// See also [WebView].
|
||||||
@ProviderFor(WebView)
|
@ProviderFor(WebView)
|
||||||
|
|||||||
@@ -24,124 +24,121 @@ class WebViewScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
ref.read(webViewProvider).webViewController.loadRequest(Uri.parse(bookmark.url!));
|
ref.read(webViewProvider.notifier).loadNewUrl(bookmark.url!);
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
[bookmark],
|
[bookmark],
|
||||||
);
|
);
|
||||||
|
|
||||||
return ScaffoldMessenger(
|
return Scaffold(
|
||||||
key: ScaffoldMessengerKeys.webview,
|
appBar: AppBar(
|
||||||
child: Scaffold(
|
elevation: 3,
|
||||||
appBar: AppBar(
|
title: Column(
|
||||||
elevation: 3,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
title: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Text(
|
||||||
children: [
|
bookmark.title != "" ? bookmark.title! : bookmark.websiteTitle!,
|
||||||
Text(
|
style: const TextStyle(fontSize: 14),
|
||||||
bookmark.title != "" ? bookmark.title! : bookmark.websiteTitle!,
|
),
|
||||||
style: const TextStyle(fontSize: 14),
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
bookmark.url!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
),
|
||||||
Text(
|
],
|
||||||
bookmark.url!,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
bottom: PreferredSize(
|
|
||||||
preferredSize: const Size(double.maxFinite, 0),
|
|
||||||
child: ref.watch(webViewProvider).loadProgress < 100
|
|
||||||
? const LinearProgressIndicator()
|
|
||||||
: const SizedBox(
|
|
||||||
height: 4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
bottom: PreferredSize(
|
||||||
child: Column(
|
preferredSize: const Size(double.maxFinite, 0),
|
||||||
children: [
|
child: ref.watch(webViewProvider).loadProgress < 100
|
||||||
Expanded(
|
? const LinearProgressIndicator()
|
||||||
child: WebViewWidget(
|
: const SizedBox(
|
||||||
controller: ref.watch(webViewProvider).webViewController,
|
height: 4,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: WebViewWidget(
|
||||||
|
controller: ref.watch(webViewProvider).webViewController,
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
Padding(
|
||||||
child: Row(
|
padding: const EdgeInsets.all(8.0),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
child: Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Row(
|
||||||
IconButton(
|
children: [
|
||||||
onPressed: ref.watch(webViewProvider).canGoBack == true
|
IconButton(
|
||||||
? () => ref.watch(webViewProvider).webViewController.goBack()
|
onPressed: ref.watch(webViewProvider).canGoBack == true
|
||||||
: null,
|
? () => ref.watch(webViewProvider).webViewController.goBack()
|
||||||
icon: const Icon(Icons.arrow_back_rounded),
|
: null,
|
||||||
tooltip: t.webview.goForward,
|
icon: const Icon(Icons.arrow_back_rounded),
|
||||||
|
tooltip: t.webview.goForward,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
IconButton(
|
||||||
|
onPressed: ref.watch(webViewProvider).canGoForward == true
|
||||||
|
? () => ref.watch(webViewProvider).webViewController.goForward()
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_forward_rounded),
|
||||||
|
tooltip: t.webview.goForward,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => ref.watch(webViewProvider).webViewController.reload(),
|
||||||
|
icon: const Icon(Icons.refresh_rounded),
|
||||||
|
tooltip: t.webview.reload,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
|
itemBuilder: (context) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () => Share.shareUri(Uri.parse(bookmark.url!)),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.share_rounded),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Flexible(child: Text(t.webview.share)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
),
|
||||||
IconButton(
|
PopupMenuItem(
|
||||||
onPressed: ref.watch(webViewProvider).canGoForward == true
|
onTap: () => copyToClipboard(
|
||||||
? () => ref.watch(webViewProvider).webViewController.goForward()
|
key: ScaffoldMessengerKeys.webview,
|
||||||
: null,
|
value: bookmark.url!,
|
||||||
icon: const Icon(Icons.arrow_forward_rounded),
|
successMessage: t.webview.linkCopiedClipboard,
|
||||||
tooltip: t.webview.goForward,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
child: Row(
|
||||||
IconButton(
|
children: [
|
||||||
onPressed: () => ref.watch(webViewProvider).webViewController.reload(),
|
const Icon(Icons.copy_rounded),
|
||||||
icon: const Icon(Icons.refresh_rounded),
|
const SizedBox(width: 12),
|
||||||
tooltip: t.webview.reload,
|
Flexible(child: Text(t.webview.copyLinkClipboard)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
PopupMenuItem(
|
||||||
PopupMenuButton(
|
onTap: () => openUrl(bookmark.url!),
|
||||||
itemBuilder: (context) => [
|
child: Row(
|
||||||
PopupMenuItem(
|
children: [
|
||||||
onTap: () => Share.shareUri(Uri.parse(bookmark.url!)),
|
const Icon(Icons.open_in_browser_rounded),
|
||||||
child: Row(
|
const SizedBox(width: 12),
|
||||||
children: [
|
Flexible(child: Text(t.webview.openInSystemBrowser)),
|
||||||
const Icon(Icons.share_rounded),
|
],
|
||||||
const SizedBox(width: 12),
|
|
||||||
Flexible(child: Text(t.webview.share)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
),
|
||||||
onTap: () => copyToClipboard(
|
],
|
||||||
key: ScaffoldMessengerKeys.webview,
|
),
|
||||||
value: bookmark.url!,
|
],
|
||||||
successMessage: t.webview.linkCopiedClipboard,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.copy_rounded),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Flexible(child: Text(t.webview.copyLinkClipboard)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
onTap: () => openUrl(bookmark.url!),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.open_in_browser_rounded),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Flexible(child: Text(t.webview.openInSystemBrowser)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user