Adapted bookmarks list to tablet mode

This commit is contained in:
Juan Gilsanz Polo
2024-02-28 20:18:54 +01:00
parent c777ccbbca
commit d13e521481
19 changed files with 891 additions and 671 deletions

View File

@@ -6,7 +6,7 @@
/// Locales: 2
/// Strings: 350 (175 per locale)
///
/// Built on 2024-02-28 at 16:44 UTC
/// Built on 2024-02-28 at 18:58 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
@@ -481,7 +481,7 @@ class _StringsSettingsGeneralSettingsEn {
String get disconnectFromServer => 'Disconnect from server';
late final _StringsSettingsGeneralSettingsDisconnectModalEn disconnectModal = _StringsSettingsGeneralSettingsDisconnectModalEn._(_root);
String get useInAppBrowser => 'Use in app browser';
String get useInAppBrowserDescription => 'Opens the bookmarks with the integrated browser instead of with the system browser.';
String get useInAppBrowserDescription => 'Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.';
}
// Path: settings.generalSettings.disconnectModal
@@ -852,7 +852,7 @@ class _StringsSettingsGeneralSettingsEs implements _StringsSettingsGeneralSettin
@override String get disconnectFromServer => 'Desconectar del servidor';
@override late final _StringsSettingsGeneralSettingsDisconnectModalEs disconnectModal = _StringsSettingsGeneralSettingsDisconnectModalEs._(_root);
@override String get useInAppBrowser => 'Usar navegador de la aplicación';
@override String get useInAppBrowserDescription => 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema.';
@override String get useInAppBrowserDescription => 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado.';
}
// Path: settings.generalSettings.disconnectModal
@@ -1028,7 +1028,7 @@ extension on Translations {
case 'settings.generalSettings.disconnectModal.title': return 'Disconnect';
case 'settings.generalSettings.disconnectModal.description': return 'Are you sure you want to disconnect from the server?\nYou will be redirected to the initial setup.';
case 'settings.generalSettings.useInAppBrowser': return 'Use in app browser';
case 'settings.generalSettings.useInAppBrowserDescription': return 'Opens the bookmarks with the integrated browser instead of with the system browser.';
case 'settings.generalSettings.useInAppBrowserDescription': return 'Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.';
case 'webview.goBack': return 'Go back';
case 'webview.goForward': return 'Go forward';
case 'webview.reload': return 'Reload';
@@ -1211,7 +1211,7 @@ extension on _StringsEs {
case 'settings.generalSettings.disconnectModal.title': return 'Desconectar';
case 'settings.generalSettings.disconnectModal.description': return '¿Estás seguro que deseas desconectarte del servidor?\nSerás redirigido a la configuración inicial.';
case 'settings.generalSettings.useInAppBrowser': return 'Usar navegador de la aplicación';
case 'settings.generalSettings.useInAppBrowserDescription': return 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema.';
case 'settings.generalSettings.useInAppBrowserDescription': return 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado.';
case 'webview.goBack': return 'Ir atrás';
case 'webview.goForward': return 'Ir adelante';
case 'webview.reload': return 'Recargar';

View File

@@ -183,7 +183,7 @@
"description": "Are you sure you want to disconnect from the server?\nYou will be redirected to the initial setup."
},
"useInAppBrowser": "Use in app browser",
"useInAppBrowserDescription": "Opens the bookmarks with the integrated browser instead of with the system browser."
"useInAppBrowserDescription": "Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used."
}
},
"webview": {

View File

@@ -183,7 +183,7 @@
"description": "¿Estás seguro que deseas desconectarte del servidor?\nSerás redirigido a la configuración inicial."
},
"useInAppBrowser": "Usar navegador de la aplicación",
"useInAppBrowserDescription": "Abre los marcadores con el navegador integrado en vez de con el navegador del sietema."
"useInAppBrowserDescription": "Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado."
}
},
"webview": {

View File

@@ -10,6 +10,7 @@ class BookmarksModel {
bool loadingMore;
int maxNumber;
ReadStatus readStatus;
Bookmark? selectedBookmark;
BookmarksModel({
this.currentPage = 0,
@@ -19,5 +20,6 @@ class BookmarksModel {
this.loadingMore = false,
this.maxNumber = 0,
this.readStatus = ReadStatus.all,
this.selectedBookmark,
});
}

View File

@@ -13,6 +13,7 @@ class SearchBookmarksModel {
LoadStatus inialLoadStatus;
bool loadingMore;
int maxNumber;
Bookmark? selectedBookmark;
SearchBookmarksModel({
required this.searchController,
@@ -23,5 +24,6 @@ class SearchBookmarksModel {
this.inialLoadStatus = LoadStatus.loaded,
this.loadingMore = false,
this.maxNumber = 0,
this.selectedBookmark,
});
}

View File

@@ -1,10 +1,15 @@
import 'package:linkdy/constants/global_keys.dart';
import 'package:riverpod_annotation/riverpod_annotation.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/model/bookmarks.model.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/constants/global_keys.dart';
import 'package:linkdy/providers/app_status.provider.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/utils/open_url.dart';
import 'package:linkdy/models/data/bookmarks.dart';
import 'package:linkdy/providers/api_client.provider.dart';
import 'package:linkdy/constants/enums.dart';
@@ -93,6 +98,16 @@ class Bookmarks extends _$Bookmarks {
ref.notifyListeners();
}
void selectBookmark(Bookmark bookmark, double width) {
if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
openUrl(bookmark.url!);
}
state.selectedBookmark = bookmark;
ref.notifyListeners();
}
Future<void> refresh() async {
await ref.read(bookmarksRequestProvider(state.readStatus, state.limit).future);
}

View File

@@ -189,7 +189,7 @@ final bookmarksRequestLoadMoreProvider =
);
typedef BookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef<void>;
String _$bookmarksHash() => r'6ebfea9e1b2b70e692527de3a3cccd0c85946c12';
String _$bookmarksHash() => r'80e94e586950b9072f229958f98c88069086d7ab';
/// See also [Bookmarks].
@ProviderFor(Bookmarks)

View File

@@ -6,6 +6,11 @@ import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
import 'package:linkdy/screens/bookmarks/model/search_bookmarks.model.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/providers/app_status.provider.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/utils/open_url.dart';
import 'package:linkdy/constants/global_keys.dart';
import 'package:linkdy/constants/enums.dart';
import 'package:linkdy/models/data/bookmarks.dart';
@@ -99,6 +104,16 @@ class SearchBookmarks extends _$SearchBookmarks {
ref.notifyListeners();
}
void selectBookmark(Bookmark bookmark, double width) {
if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
openUrl(bookmark.url!);
}
state.selectedBookmark = bookmark;
ref.notifyListeners();
}
void deleteBookmark(Bookmark bookmark) async {
final result = await BookmarkCommonFunctions.deleteBookmark<SearchBookmarksModel>(
ref: ref,

View File

@@ -174,7 +174,7 @@ final fetchSearchBookmarksLoadMoreProvider =
);
typedef FetchSearchBookmarksLoadMoreRef = AutoDisposeFutureProviderRef<void>;
String _$searchBookmarksHash() => r'bdb0eedf3ebdde4b2cb4795efe61ce42e4c85d00';
String _$searchBookmarksHash() => r'3daf460b8389e8bcf8498c4bdf3935e88f4ce156';
/// See also [SearchBookmarks].
@ProviderFor(SearchBookmarks)

View File

@@ -11,27 +11,30 @@ import 'package:linkdy/config/options.dart';
import 'package:linkdy/i18n/strings.g.dart';
import 'package:linkdy/models/data/bookmarks.dart';
import 'package:linkdy/providers/app_status.provider.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/utils/date_to_string.dart';
import 'package:linkdy/utils/open_url.dart';
class BookmarkItem extends ConsumerWidget {
final Bookmark bookmark;
final void Function(Bookmark bookmark) onSelect;
final void Function(Bookmark bookmark) onDelete;
final void Function(Bookmark bookmark) onReadUnread;
final void Function(Bookmark bookmark) onArchiveUnarchive;
final void Function(Bookmark bookmark) onEdit;
final void Function(Bookmark bookmark) onShareInternally;
final bool selected;
final bool tabletMode;
const BookmarkItem({
super.key,
required this.bookmark,
required this.onSelect,
required this.onDelete,
required this.onReadUnread,
required this.onArchiveUnarchive,
required this.onEdit,
required this.onShareInternally,
required this.selected,
required this.tabletMode,
});
@override
@@ -46,7 +49,11 @@ class BookmarkItem extends ConsumerWidget {
}
}
return Slidable(
return Padding(
padding: tabletMode ? const EdgeInsets.symmetric(horizontal: 8) : const EdgeInsets.all(0),
child: ClipRRect(
borderRadius: tabletMode ? BorderRadius.circular(28) : BorderRadius.circular(0),
child: Slidable(
key: ValueKey(bookmark.id!),
groupTag: ConfigOptions.slidableGroupTag,
startActionPane: ActionPane(
@@ -101,10 +108,10 @@ class BookmarkItem extends ConsumerWidget {
),
],
),
child: Material(
color: selected && tabletMode ? Theme.of(context).colorScheme.primaryContainer : Colors.transparent,
child: InkWell(
onTap: ref.watch(appStatusProvider).useInAppBrowser == true
? () => ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark)
: () => openUrl(bookmark.url!),
onTap: () => onSelect(bookmark),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
@@ -296,7 +303,9 @@ class BookmarkItem extends ConsumerWidget {
),
],
if (bookmark.dateModified != null) ...[
if (bookmark.unread == true || bookmark.shared == true || bookmark.tagNames?.isNotEmpty == true)
if (bookmark.unread == true ||
bookmark.shared == true ||
bookmark.tagNames?.isNotEmpty == true)
Container(
width: 1,
height: 12,
@@ -317,6 +326,9 @@ class BookmarkItem extends ConsumerWidget {
),
),
),
),
),
),
);
}
}

View File

@@ -1,17 +1,19 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:linkdy/screens/bookmarks/ui/visualization_modal.dart';
import 'package:linkdy/screens/bookmarks/ui/visualization_modal.dart';
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
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/delete_bookmark_modal.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/error_screen.dart';
import 'package:linkdy/widgets/no_data_screen.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/constants/enums.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
@@ -23,6 +25,46 @@ final GlobalKey _searchButtonKey = GlobalKey();
class BookmarksScreen extends ConsumerWidget {
const BookmarksScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.bookmarks,
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > Sizes.tabletBreakpoint) {
return Row(
children: [
const Expanded(flex: 2, child: _List(tabletMode: true)),
if (ref.watch(bookmarksProvider).selectedBookmark != null)
Expanded(
flex: 3,
child: WebViewScreen(
bookmark: ref.watch(bookmarksProvider).selectedBookmark!,
),
),
if (ref.watch(bookmarksProvider).selectedBookmark == null)
const Expanded(
flex: 3,
child: SizedBox(),
),
],
);
} else {
return const _List(tabletMode: false);
}
},
),
);
}
}
class _List extends ConsumerWidget {
final bool tabletMode;
const _List({
required this.tabletMode,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final bookmarks = ref.watch(bookmarksProvider);
@@ -51,9 +93,7 @@ class BookmarksScreen extends ConsumerWidget {
return false;
}
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.bookmarks,
child: Scaffold(
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverOverlapAbsorber(
@@ -203,6 +243,7 @@ class BookmarksScreen extends ConsumerWidget {
}
return BookmarkItem(
bookmark: bookmarks.bookmarks[index],
onSelect: (b) => ref.read(bookmarksProvider.notifier).selectBookmark(b, width),
onReadUnread: ref.read(bookmarksProvider.notifier).markAsReadUnread,
onDelete: (bookmark) => showDialog(
context: context,
@@ -214,6 +255,8 @@ class BookmarksScreen extends ConsumerWidget {
onArchiveUnarchive: ref.read(bookmarksProvider.notifier).archiveUnarchive,
onShareInternally: ref.read(bookmarksProvider.notifier).shareUnshare,
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
selected: bookmarks.bookmarks[index] == bookmarks.selectedBookmark,
tabletMode: tabletMode,
);
},
),
@@ -229,7 +272,6 @@ class BookmarksScreen extends ConsumerWidget {
onPressed: () => openBookmarkFormModal(context: context, width: width),
child: const Icon(Icons.add_rounded),
),
),
);
}
}

View File

@@ -6,15 +6,17 @@ 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_item.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/no_data_screen.dart';
import 'package:linkdy/widgets/error_screen.dart';
import 'package:linkdy/constants/global_keys.dart';
import 'package:linkdy/constants/enums.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/i18n/strings.g.dart';
import 'package:linkdy/widgets/no_data_screen.dart';
class SearchBookmarksModal extends ConsumerWidget {
final bool fullscreen;
@@ -24,6 +26,50 @@ class SearchBookmarksModal extends ConsumerWidget {
required this.fullscreen,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.search,
child: Dialog.fullscreen(
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > Sizes.tabletBreakpoint) {
return Row(
children: [
const Expanded(flex: 2, child: _List(tabletMode: true)),
if (ref.watch(searchBookmarksProvider).selectedBookmark != null)
Expanded(
flex: 3,
child: WebViewScreen(
bookmark: ref.watch(searchBookmarksProvider).selectedBookmark!,
),
),
if (ref.watch(searchBookmarksProvider).selectedBookmark == null)
Expanded(
flex: 3,
child: Container(
color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2),
),
),
],
);
} else {
return const _List(tabletMode: false);
}
},
),
),
);
}
}
class _List extends ConsumerWidget {
final bool tabletMode;
const _List({
required this.tabletMode,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = ref.watch(searchBookmarksProvider);
@@ -40,10 +86,7 @@ class SearchBookmarksModal extends ConsumerWidget {
return false;
}
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.search,
child: Dialog.fullscreen(
child: Scaffold(
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2),
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0),
@@ -131,6 +174,7 @@ class SearchBookmarksModal extends ConsumerWidget {
}
return BookmarkItem(
bookmark: provider.bookmarks[index],
onSelect: (b) => ref.read(searchBookmarksProvider.notifier).selectBookmark(b, width),
onReadUnread: ref.read(searchBookmarksProvider.notifier).markAsReadUnread,
onDelete: (bookmark) => showDialog(
context: context,
@@ -142,6 +186,8 @@ class SearchBookmarksModal extends ConsumerWidget {
onArchiveUnarchive: ref.read(searchBookmarksProvider.notifier).archiveUnarchive,
onShareInternally: ref.read(searchBookmarksProvider.notifier).shareUnshare,
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
selected: provider.bookmarks[index] == provider.selectedBookmark,
tabletMode: tabletMode,
);
},
),
@@ -149,8 +195,6 @@ class SearchBookmarksModal extends ConsumerWidget {
);
},
),
),
),
);
}
}

View File

@@ -13,6 +13,7 @@ class FilteredBookmarksModel {
List<Bookmark> bookmarks;
int maxNumber;
bool loadingMore;
Bookmark? selectedBookmark;
FilteredBookmarksModel({
this.filteredBookmarksMode = FilteredBookmarksMode.shared,
@@ -24,5 +25,6 @@ class FilteredBookmarksModel {
required this.bookmarks,
this.maxNumber = 0,
this.loadingMore = false,
this.selectedBookmark,
});
}

View File

@@ -1,4 +1,3 @@
import 'package:linkdy/constants/global_keys.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:linkdy/screens/bookmarks/provider/favicon_loader.provider.dart';
@@ -6,6 +5,12 @@ import 'package:linkdy/screens/bookmarks/provider/common_functions.dart';
import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart';
import 'package:linkdy/screens/filtered_bookmarks/model/filtered_bookmarks.model.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/constants/global_keys.dart';
import 'package:linkdy/providers/app_status.provider.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/utils/open_url.dart';
import 'package:linkdy/models/data/bookmarks.dart';
import 'package:linkdy/constants/enums.dart';
import 'package:linkdy/models/data/tags.dart';
@@ -149,6 +154,16 @@ class FilteredBookmarks extends _$FilteredBookmarks {
ref.notifyListeners();
}
void selectBookmark(Bookmark bookmark, double width) {
if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark);
} else if (width <= Sizes.tabletBreakpoint && ref.watch(appStatusProvider).useInAppBrowser == true) {
openUrl(bookmark.url!);
}
state.selectedBookmark = bookmark;
ref.notifyListeners();
}
Future<void> refresh() async {
if (state.filteredBookmarksMode == FilteredBookmarksMode.tag) {
await ref.read(

View File

@@ -372,7 +372,7 @@ final filteredBookmarksRequestLoadMoreProvider =
typedef FilteredBookmarksRequestLoadMoreRef
= AutoDisposeFutureProviderRef<void>;
String _$filteredBookmarksHash() => r'fdd67391d76f2bf8fd879b2f64a30d54922c4938';
String _$filteredBookmarksHash() => r'584c9ee245200f653d43b10d807860dcbac68ff5';
/// See also [FilteredBookmarks].
@ProviderFor(FilteredBookmarks)

View File

@@ -1,14 +1,17 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:hooks_riverpod/hooks_riverpod.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/delete_bookmark_modal.dart';
import 'package:linkdy/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart';
import 'package:linkdy/screens/webview/ui/webview.dart';
import 'package:linkdy/widgets/error_screen.dart';
import 'package:linkdy/widgets/no_data_screen.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/constants/global_keys.dart';
import 'package:linkdy/models/data/tags.dart';
import 'package:linkdy/constants/enums.dart';
@@ -16,7 +19,7 @@ import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/i18n/strings.g.dart';
class FilteredBookmarksScreen extends ConsumerStatefulWidget {
class FilteredBookmarksScreen extends HookConsumerWidget {
final FilteredBookmarksMode filteredBookmarksMode;
final String? tagId;
final Tag? tag;
@@ -29,15 +32,12 @@ class FilteredBookmarksScreen extends ConsumerStatefulWidget {
});
@override
FilteredBookmarksScreenState createState() => FilteredBookmarksScreenState();
}
class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen> {
@override
void initState() {
ref.read(filteredBookmarksProvider.notifier).setMode(widget.filteredBookmarksMode);
if (widget.filteredBookmarksMode == FilteredBookmarksMode.tag) {
if (widget.tag == null && widget.tagId == null) {
Widget build(BuildContext context, WidgetRef ref) {
useEffect(
() {
ref.read(filteredBookmarksProvider.notifier).setMode(filteredBookmarksMode);
if (filteredBookmarksMode == FilteredBookmarksMode.tag) {
if (tag == null && tagId == null) {
final router = ref.read(routerProvider);
while (router.canPop() == true) {
router.pop();
@@ -45,28 +45,84 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
router.pushReplacement(RoutesPaths.bookmarks);
return;
}
if (widget.tag != null) {
ref.read(filteredBookmarksProvider).tag = widget.tag;
if (tag != null) {
ref.read(filteredBookmarksProvider).tag = tag;
}
if (widget.tagId != null) {
ref.read(filteredBookmarksProvider).tagId = widget.tagId;
if (tagId != null) {
ref.read(filteredBookmarksProvider).tagId = tagId;
}
ref.read(tagBookmarksRequestProvider(widget.tag, widget.tagId, ref.read(filteredBookmarksProvider).limit));
ref.read(tagBookmarksRequestProvider(tag, tagId, ref.read(filteredBookmarksProvider).limit));
} else {
ref.read(
filteredBookmarksRequestProvider(widget.filteredBookmarksMode, ref.read(filteredBookmarksProvider).limit),
filteredBookmarksRequestProvider(filteredBookmarksMode, ref.read(filteredBookmarksProvider).limit),
);
}
return null;
},
[filteredBookmarksMode, tagId, tag],
);
super.initState();
}
@override
Widget build(BuildContext context) {
if (widget.filteredBookmarksMode == FilteredBookmarksMode.tag && widget.tag == null && widget.tagId == null) {
if (filteredBookmarksMode == FilteredBookmarksMode.tag && tag == null && tagId == null) {
return const Material();
}
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.filteredBookmarks,
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > Sizes.tabletBreakpoint) {
return Material(
child: Row(
children: [
Expanded(
flex: 2,
child: _List(
filteredBookmarksMode: filteredBookmarksMode,
tag: tag,
tabletMode: true,
),
),
if (ref.watch(filteredBookmarksProvider).selectedBookmark != null)
Expanded(
flex: 3,
child: WebViewScreen(
bookmark: ref.watch(filteredBookmarksProvider).selectedBookmark!,
),
),
if (ref.watch(filteredBookmarksProvider).selectedBookmark == null)
const Expanded(
flex: 3,
child: SizedBox(),
),
],
),
);
} else {
return _List(
filteredBookmarksMode: filteredBookmarksMode,
tag: tag,
tabletMode: false,
);
}
},
),
);
}
}
class _List extends ConsumerWidget {
final bool tabletMode;
final FilteredBookmarksMode filteredBookmarksMode;
final Tag? tag;
const _List({
required this.filteredBookmarksMode,
this.tag,
required this.tabletMode,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = ref.watch(filteredBookmarksProvider);
final width = MediaQuery.of(context).size.width;
@@ -82,10 +138,10 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
}
String title() {
switch (widget.filteredBookmarksMode) {
switch (filteredBookmarksMode) {
case FilteredBookmarksMode.tag:
return widget.tag != null
? "#${widget.tag!.name}"
return tag != null
? "#${tag!.name}"
: provider.tag != null
? "#${provider.tag!.name}"
: '';
@@ -102,7 +158,7 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
}
String noContent() {
switch (widget.filteredBookmarksMode) {
switch (filteredBookmarksMode) {
case FilteredBookmarksMode.tag:
return t.tags.filteredBookmarks.noBookmarksWithThisTag;
@@ -117,9 +173,7 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
}
}
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.filteredBookmarks,
child: Scaffold(
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverOverlapAbsorber(
@@ -165,9 +219,8 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
if (provider.bookmarks.isNotEmpty)
SlidableAutoCloseBehavior(
child: SliverList.builder(
itemCount: provider.loadingMore == true
? provider.bookmarks.length + 1
: provider.bookmarks.length,
itemCount:
provider.loadingMore == true ? provider.bookmarks.length + 1 : provider.bookmarks.length,
itemBuilder: (context, index) {
if (provider.loadingMore == true && index == provider.bookmarks.length) {
return const Padding(
@@ -179,6 +232,7 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
}
return BookmarkItem(
bookmark: provider.bookmarks[index],
onSelect: (b) => ref.read(filteredBookmarksProvider.notifier).selectBookmark(b, width),
onReadUnread: ref.read(filteredBookmarksProvider.notifier).markAsReadUnread,
onDelete: (bookmark) => showDialog(
context: context,
@@ -190,6 +244,8 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
onArchiveUnarchive: ref.read(filteredBookmarksProvider.notifier).archiveUnarchive,
onShareInternally: ref.read(filteredBookmarksProvider.notifier).shareUnshare,
onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b),
selected: provider.bookmarks[index] == provider.selectedBookmark,
tabletMode: tabletMode,
);
},
),
@@ -201,7 +257,6 @@ class FilteredBookmarksScreenState extends ConsumerState<FilteredBookmarksScreen
),
),
),
),
);
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:share_plus/share_plus.dart';
import 'package:linkdy/screens/webview/provider/webview.provider.dart';
@@ -11,7 +12,7 @@ import 'package:linkdy/i18n/strings.g.dart';
import 'package:linkdy/utils/copy_clipboard.dart';
import 'package:linkdy/utils/open_url.dart';
class WebViewScreen extends ConsumerStatefulWidget {
class WebViewScreen extends HookConsumerWidget {
final Bookmark bookmark;
const WebViewScreen({
@@ -20,18 +21,15 @@ class WebViewScreen extends ConsumerStatefulWidget {
});
@override
WebViewScreenState createState() => WebViewScreenState();
}
Widget build(BuildContext context, WidgetRef ref) {
useEffect(
() {
ref.read(webViewProvider).webViewController.loadRequest(Uri.parse(bookmark.url!));
return null;
},
[bookmark],
);
class WebViewScreenState extends ConsumerState<WebViewScreen> {
@override
void initState() {
ref.read(webViewProvider).webViewController.loadRequest(Uri.parse(widget.bookmark.url!));
super.initState();
}
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
key: ScaffoldMessengerKeys.webview,
child: Scaffold(
@@ -41,12 +39,12 @@ class WebViewScreenState extends ConsumerState<WebViewScreen> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.bookmark.title != "" ? widget.bookmark.title! : widget.bookmark.websiteTitle!,
bookmark.title != "" ? bookmark.title! : bookmark.websiteTitle!,
style: const TextStyle(fontSize: 14),
),
const SizedBox(height: 4),
Text(
widget.bookmark.url!,
bookmark.url!,
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
@@ -104,7 +102,7 @@ class WebViewScreenState extends ConsumerState<WebViewScreen> {
PopupMenuButton(
itemBuilder: (context) => [
PopupMenuItem(
onTap: () => Share.shareUri(Uri.parse(widget.bookmark.url!)),
onTap: () => Share.shareUri(Uri.parse(bookmark.url!)),
child: Row(
children: [
const Icon(Icons.share_rounded),
@@ -116,7 +114,7 @@ class WebViewScreenState extends ConsumerState<WebViewScreen> {
PopupMenuItem(
onTap: () => copyToClipboard(
key: ScaffoldMessengerKeys.webview,
value: widget.bookmark.url!,
value: bookmark.url!,
successMessage: t.webview.linkCopiedClipboard,
),
child: Row(
@@ -128,7 +126,7 @@ class WebViewScreenState extends ConsumerState<WebViewScreen> {
),
),
PopupMenuItem(
onTap: () => openUrl(widget.bookmark.url!),
onTap: () => openUrl(bookmark.url!),
child: Row(
children: [
const Icon(Icons.open_in_browser_rounded),

View File

@@ -390,6 +390,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.1.0"
flutter_hooks:
dependency: "direct main"
description:
name: flutter_hooks
sha256: cde36b12f7188c85286fba9b38cc5a902e7279f36dd676967106c041dc9dde70
url: "https://pub.dev"
source: hosted
version: "0.20.5"
flutter_launcher_icons:
dependency: "direct dev"
description:
@@ -493,6 +501,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.1"
hooks_riverpod:
dependency: "direct main"
description:
name: hooks_riverpod
sha256: "758b07eba336e3cbacbd81dba481f2228a14102083fdde07045e8514e8054c49"
url: "https://pub.dev"
source: hosted
version: "2.4.10"
hotreloader:
dependency: transitive
description:

View File

@@ -57,6 +57,8 @@ dependencies:
http: ^1.2.0
flutter_slidable: ^3.0.1
webview_flutter: ^4.7.0
flutter_hooks: ^0.20.5
hooks_riverpod: ^2.4.10
dev_dependencies:
build_runner: ^2.4.8