List tags
This commit is contained in:
@@ -10,6 +10,11 @@ final appScreens = [
|
|||||||
route: RoutesPaths.bookmarks,
|
route: RoutesPaths.bookmarks,
|
||||||
name: t.bookmarks.bookmarks,
|
name: t.bookmarks.bookmarks,
|
||||||
),
|
),
|
||||||
|
AppRoute(
|
||||||
|
icon: Icons.label_rounded,
|
||||||
|
route: RoutesPaths.tags,
|
||||||
|
name: t.tags.tags,
|
||||||
|
),
|
||||||
AppRoute(
|
AppRoute(
|
||||||
icon: Icons.settings_rounded,
|
icon: Icons.settings_rounded,
|
||||||
route: RoutesPaths.settings,
|
route: RoutesPaths.settings,
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
/// To regenerate, run: `dart run slang`
|
/// To regenerate, run: `dart run slang`
|
||||||
///
|
///
|
||||||
/// Locales: 2
|
/// Locales: 2
|
||||||
/// Strings: 222 (111 per locale)
|
/// Strings: 208 (104 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2024-02-24 at 11:55 UTC
|
/// Built on 2024-02-24 at 12:07 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
@@ -151,7 +151,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
|
|||||||
late final _StringsGenericEn generic = _StringsGenericEn._(_root);
|
late final _StringsGenericEn generic = _StringsGenericEn._(_root);
|
||||||
late final _StringsOnboardingEn onboarding = _StringsOnboardingEn._(_root);
|
late final _StringsOnboardingEn onboarding = _StringsOnboardingEn._(_root);
|
||||||
late final _StringsBookmarksEn bookmarks = _StringsBookmarksEn._(_root);
|
late final _StringsBookmarksEn bookmarks = _StringsBookmarksEn._(_root);
|
||||||
late final _StringsSearchEn search = _StringsSearchEn._(_root);
|
late final _StringsTagsEn tags = _StringsTagsEn._(_root);
|
||||||
late final _StringsSettingsEn settings = _StringsSettingsEn._(_root);
|
late final _StringsSettingsEn settings = _StringsSettingsEn._(_root);
|
||||||
late final _StringsWebviewEn webview = _StringsWebviewEn._(_root);
|
late final _StringsWebviewEn webview = _StringsWebviewEn._(_root);
|
||||||
late final _StringsColorsEn colors = _StringsColorsEn._(_root);
|
late final _StringsColorsEn colors = _StringsColorsEn._(_root);
|
||||||
@@ -219,21 +219,14 @@ class _StringsBookmarksEn {
|
|||||||
late final _StringsBookmarksSearchEn search = _StringsBookmarksSearchEn._(_root);
|
late final _StringsBookmarksSearchEn search = _StringsBookmarksSearchEn._(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: search
|
// Path: tags
|
||||||
class _StringsSearchEn {
|
class _StringsTagsEn {
|
||||||
_StringsSearchEn._(this._root);
|
_StringsTagsEn._(this._root);
|
||||||
|
|
||||||
final Translations _root; // ignore: unused_field
|
final Translations _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
String get search => 'Search';
|
|
||||||
String get bookmarks => 'Bookmarks';
|
|
||||||
String get tags => 'Tags';
|
String get tags => 'Tags';
|
||||||
String get clearSearch => 'Clear search';
|
|
||||||
String get inputSearchTerm => 'Input a search term';
|
|
||||||
String get cannotSearchError => 'Cannot search content due to an error';
|
|
||||||
String get inputtedSearchTermNoResults => 'The inputted search term doesn\'t have any results';
|
|
||||||
String created({required Object created}) => 'Created: ${created}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: settings
|
// Path: settings
|
||||||
@@ -418,7 +411,7 @@ class _StringsEs implements Translations {
|
|||||||
@override late final _StringsGenericEs generic = _StringsGenericEs._(_root);
|
@override late final _StringsGenericEs generic = _StringsGenericEs._(_root);
|
||||||
@override late final _StringsOnboardingEs onboarding = _StringsOnboardingEs._(_root);
|
@override late final _StringsOnboardingEs onboarding = _StringsOnboardingEs._(_root);
|
||||||
@override late final _StringsBookmarksEs bookmarks = _StringsBookmarksEs._(_root);
|
@override late final _StringsBookmarksEs bookmarks = _StringsBookmarksEs._(_root);
|
||||||
@override late final _StringsSearchEs search = _StringsSearchEs._(_root);
|
@override late final _StringsTagsEs tags = _StringsTagsEs._(_root);
|
||||||
@override late final _StringsSettingsEs settings = _StringsSettingsEs._(_root);
|
@override late final _StringsSettingsEs settings = _StringsSettingsEs._(_root);
|
||||||
@override late final _StringsWebviewEs webview = _StringsWebviewEs._(_root);
|
@override late final _StringsWebviewEs webview = _StringsWebviewEs._(_root);
|
||||||
@override late final _StringsColorsEs colors = _StringsColorsEs._(_root);
|
@override late final _StringsColorsEs colors = _StringsColorsEs._(_root);
|
||||||
@@ -486,21 +479,14 @@ class _StringsBookmarksEs implements _StringsBookmarksEn {
|
|||||||
@override late final _StringsBookmarksSearchEs search = _StringsBookmarksSearchEs._(_root);
|
@override late final _StringsBookmarksSearchEs search = _StringsBookmarksSearchEs._(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: search
|
// Path: tags
|
||||||
class _StringsSearchEs implements _StringsSearchEn {
|
class _StringsTagsEs implements _StringsTagsEn {
|
||||||
_StringsSearchEs._(this._root);
|
_StringsTagsEs._(this._root);
|
||||||
|
|
||||||
@override final _StringsEs _root; // ignore: unused_field
|
@override final _StringsEs _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get search => 'Buscar';
|
|
||||||
@override String get bookmarks => 'Marcadores';
|
|
||||||
@override String get tags => 'Etiquetas';
|
@override String get tags => 'Etiquetas';
|
||||||
@override String get clearSearch => 'Limpiar búsqueda';
|
|
||||||
@override String get inputSearchTerm => 'Introduce un término de búsqueda';
|
|
||||||
@override String get cannotSearchError => 'No se puede buscar el contenido por un error';
|
|
||||||
@override String get inputtedSearchTermNoResults => 'El término de búsqueda introducido no tiene resultados';
|
|
||||||
@override String created({required Object created}) => 'Creado: ${created}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: settings
|
// Path: settings
|
||||||
@@ -727,14 +713,7 @@ extension on Translations {
|
|||||||
case 'bookmarks.search.inputSearchTerm': return 'Input a search term';
|
case 'bookmarks.search.inputSearchTerm': return 'Input a search term';
|
||||||
case 'bookmarks.search.cannotSearchError': return 'Cannot search content due to an error';
|
case 'bookmarks.search.cannotSearchError': return 'Cannot search content due to an error';
|
||||||
case 'bookmarks.search.inputtedSearchTermNoResults': return 'The inputted search term doesn\'t have any results';
|
case 'bookmarks.search.inputtedSearchTermNoResults': return 'The inputted search term doesn\'t have any results';
|
||||||
case 'search.search': return 'Search';
|
case 'tags.tags': return 'Tags';
|
||||||
case 'search.bookmarks': return 'Bookmarks';
|
|
||||||
case 'search.tags': return 'Tags';
|
|
||||||
case 'search.clearSearch': return 'Clear search';
|
|
||||||
case 'search.inputSearchTerm': return 'Input a search term';
|
|
||||||
case 'search.cannotSearchError': return 'Cannot search content due to an error';
|
|
||||||
case 'search.inputtedSearchTermNoResults': return 'The inputted search term doesn\'t have any results';
|
|
||||||
case 'search.created': return ({required Object created}) => 'Created: ${created}';
|
|
||||||
case 'settings.settings': return 'Settings';
|
case 'settings.settings': return 'Settings';
|
||||||
case 'settings.appSettings': return 'App settings';
|
case 'settings.appSettings': return 'App settings';
|
||||||
case 'settings.aboutApp': return 'About the app';
|
case 'settings.aboutApp': return 'About the app';
|
||||||
@@ -846,14 +825,7 @@ extension on _StringsEs {
|
|||||||
case 'bookmarks.search.inputSearchTerm': return 'Introduce un término de búsqueda';
|
case 'bookmarks.search.inputSearchTerm': return 'Introduce un término de búsqueda';
|
||||||
case 'bookmarks.search.cannotSearchError': return 'No se puede buscar el contenido por un error';
|
case 'bookmarks.search.cannotSearchError': return 'No se puede buscar el contenido por un error';
|
||||||
case 'bookmarks.search.inputtedSearchTermNoResults': return 'El término de búsqueda introducido no tiene resultados';
|
case 'bookmarks.search.inputtedSearchTermNoResults': return 'El término de búsqueda introducido no tiene resultados';
|
||||||
case 'search.search': return 'Buscar';
|
case 'tags.tags': return 'Etiquetas';
|
||||||
case 'search.bookmarks': return 'Marcadores';
|
|
||||||
case 'search.tags': return 'Etiquetas';
|
|
||||||
case 'search.clearSearch': return 'Limpiar búsqueda';
|
|
||||||
case 'search.inputSearchTerm': return 'Introduce un término de búsqueda';
|
|
||||||
case 'search.cannotSearchError': return 'No se puede buscar el contenido por un error';
|
|
||||||
case 'search.inputtedSearchTermNoResults': return 'El término de búsqueda introducido no tiene resultados';
|
|
||||||
case 'search.created': return ({required Object created}) => 'Creado: ${created}';
|
|
||||||
case 'settings.settings': return 'Ajustes';
|
case 'settings.settings': return 'Ajustes';
|
||||||
case 'settings.appSettings': return 'Ajustes de la aplicación';
|
case 'settings.appSettings': return 'Ajustes de la aplicación';
|
||||||
case 'settings.aboutApp': return 'Sobre la aplicación';
|
case 'settings.aboutApp': return 'Sobre la aplicación';
|
||||||
|
|||||||
@@ -74,15 +74,8 @@
|
|||||||
"inputtedSearchTermNoResults": "The inputted search term doesn't have any results"
|
"inputtedSearchTermNoResults": "The inputted search term doesn't have any results"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"search": {
|
"tags": {
|
||||||
"search": "Search",
|
"tags": "Tags"
|
||||||
"bookmarks": "Bookmarks",
|
|
||||||
"tags": "Tags",
|
|
||||||
"clearSearch": "Clear search",
|
|
||||||
"inputSearchTerm": "Input a search term",
|
|
||||||
"cannotSearchError": "Cannot search content due to an error",
|
|
||||||
"inputtedSearchTermNoResults": "The inputted search term doesn't have any results",
|
|
||||||
"created": "Created: $created"
|
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
|||||||
@@ -74,15 +74,8 @@
|
|||||||
"inputtedSearchTermNoResults": "El término de búsqueda introducido no tiene resultados"
|
"inputtedSearchTermNoResults": "El término de búsqueda introducido no tiene resultados"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"search": {
|
"tags": {
|
||||||
"search": "Buscar",
|
"tags": "Etiquetas"
|
||||||
"bookmarks": "Marcadores",
|
|
||||||
"tags": "Etiquetas",
|
|
||||||
"clearSearch": "Limpiar búsqueda",
|
|
||||||
"inputSearchTerm": "Introduce un término de búsqueda",
|
|
||||||
"cannotSearchError": "No se puede buscar el contenido por un error",
|
|
||||||
"inputtedSearchTermNoResults": "El término de búsqueda introducido no tiene resultados",
|
|
||||||
"created": "Creado: $created"
|
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"settings": "Ajustes",
|
"settings": "Ajustes",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ class RoutesPaths {
|
|||||||
static const bookmarks = "/bookmarks";
|
static const bookmarks = "/bookmarks";
|
||||||
static const bookmarksSearch = "/bookmarks/search";
|
static const bookmarksSearch = "/bookmarks/search";
|
||||||
static const webview = "/webview";
|
static const webview = "/webview";
|
||||||
static const search = "/search";
|
static const tags = "/tags";
|
||||||
static const settings = "/settings";
|
static const settings = "/settings";
|
||||||
static const customization = "/settings/customization";
|
static const customization = "/settings/customization";
|
||||||
static const generalSettings = "/settings/general";
|
static const generalSettings = "/settings/general";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:linkdy/screens/onboarding/ui/onboarding.dart';
|
|||||||
import 'package:linkdy/screens/settings/ui/customization/customization.dart';
|
import 'package:linkdy/screens/settings/ui/customization/customization.dart';
|
||||||
import 'package:linkdy/screens/settings/ui/general_settings/general_settings.dart';
|
import 'package:linkdy/screens/settings/ui/general_settings/general_settings.dart';
|
||||||
import 'package:linkdy/screens/settings/ui/settings.dart';
|
import 'package:linkdy/screens/settings/ui/settings.dart';
|
||||||
|
import 'package:linkdy/screens/tags/ui/tags.dart';
|
||||||
import 'package:linkdy/screens/webview/ui/webview.dart';
|
import 'package:linkdy/screens/webview/ui/webview.dart';
|
||||||
import 'package:linkdy/widgets/layout.dart';
|
import 'package:linkdy/widgets/layout.dart';
|
||||||
|
|
||||||
@@ -37,6 +38,10 @@ final List<RouteBase> appRoutes = [
|
|||||||
path: RoutesPaths.bookmarks,
|
path: RoutesPaths.bookmarks,
|
||||||
builder: (context, state) => const BookmarksScreen(),
|
builder: (context, state) => const BookmarksScreen(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: RoutesPaths.tags,
|
||||||
|
builder: (context, state) => const TagsScreen(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: RoutesPaths.settings,
|
path: RoutesPaths.settings,
|
||||||
builder: (context, state) => const SettingsScreen(),
|
builder: (context, state) => const SettingsScreen(),
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class SearchBookmarksScreen extends ConsumerWidget {
|
|||||||
controller: ref.watch(searchBookmarksProvider).searchController,
|
controller: ref.watch(searchBookmarksProvider).searchController,
|
||||||
onChanged: ref.read(searchBookmarksProvider.notifier).setSearchTerm,
|
onChanged: ref.read(searchBookmarksProvider.notifier).setSearchTerm,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: t.search.search,
|
hintText: t.bookmarks.search.searchBookmarks,
|
||||||
prefixIcon: const Icon(Icons.search_rounded),
|
prefixIcon: const Icon(Icons.search_rounded),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
filled: true,
|
filled: true,
|
||||||
@@ -44,7 +44,7 @@ class SearchBookmarksScreen extends ConsumerWidget {
|
|||||||
Icons.close_rounded,
|
Icons.close_rounded,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
tooltip: t.search.clearSearch,
|
tooltip: t.bookmarks.search.clearSearch,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
|
|||||||
9
lib/screens/tags/models/tags.model.dart
Normal file
9
lib/screens/tags/models/tags.model.dart
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
class TagsModel {
|
||||||
|
int currentPage;
|
||||||
|
int limit;
|
||||||
|
|
||||||
|
TagsModel({
|
||||||
|
this.currentPage = 0,
|
||||||
|
this.limit = 100,
|
||||||
|
});
|
||||||
|
}
|
||||||
32
lib/screens/tags/provider/tags.provider.dart
Normal file
32
lib/screens/tags/provider/tags.provider.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import 'package:linkdy/screens/tags/models/tags.model.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/screens/bookmarks/model/links.model.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/models/data/tags.dart';
|
||||||
|
import 'package:linkdy/models/api_response.dart';
|
||||||
|
import 'package:linkdy/providers/api_client_provider.dart';
|
||||||
|
|
||||||
|
part 'tags.provider.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
FutureOr<ApiResponse<TagsResponse>> tagsRequest(TagsRequestRef ref) async {
|
||||||
|
final result = await ref.watch(apiClientProvider)!.fetchTags();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class Tags extends _$Tags {
|
||||||
|
@override
|
||||||
|
TagsModel build() {
|
||||||
|
return TagsModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCurrentPage(int page) {
|
||||||
|
state.currentPage = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLimit(int limit) {
|
||||||
|
state.limit = limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
lib/screens/tags/provider/tags.provider.g.dart
Normal file
40
lib/screens/tags/provider/tags.provider.g.dart
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'tags.provider.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$tagsRequestHash() => r'52b3c212ed070b39718aef1010c44fbb7120ef51';
|
||||||
|
|
||||||
|
/// See also [tagsRequest].
|
||||||
|
@ProviderFor(tagsRequest)
|
||||||
|
final tagsRequestProvider =
|
||||||
|
AutoDisposeFutureProvider<ApiResponse<TagsResponse>>.internal(
|
||||||
|
tagsRequest,
|
||||||
|
name: r'tagsRequestProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$tagsRequestHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef TagsRequestRef
|
||||||
|
= AutoDisposeFutureProviderRef<ApiResponse<TagsResponse>>;
|
||||||
|
String _$tagsHash() => r'6e26b566459377a3a6bc0f1884b9a05855151d3f';
|
||||||
|
|
||||||
|
/// See also [Tags].
|
||||||
|
@ProviderFor(Tags)
|
||||||
|
final tagsProvider = AutoDisposeNotifierProvider<Tags, TagsModel>.internal(
|
||||||
|
Tags.new,
|
||||||
|
name: r'tagsProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$tagsHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$Tags = AutoDisposeNotifier<TagsModel>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
134
lib/screens/tags/ui/tags.dart
Normal file
134
lib/screens/tags/ui/tags.dart
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/screens/tags/provider/tags.provider.dart';
|
||||||
|
import 'package:linkdy/utils/date_to_string.dart';
|
||||||
|
import 'package:linkdy/widgets/error_screen.dart';
|
||||||
|
import 'package:linkdy/widgets/no_data_screen.dart';
|
||||||
|
|
||||||
|
import 'package:linkdy/i18n/strings.g.dart';
|
||||||
|
|
||||||
|
class TagsScreen extends ConsumerWidget {
|
||||||
|
const TagsScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final tags = ref.watch(tagsRequestProvider);
|
||||||
|
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
void openAddModal() {
|
||||||
|
// showGeneralDialog(
|
||||||
|
// context: context,
|
||||||
|
// barrierColor: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)) ? Colors.transparent : Colors.black54,
|
||||||
|
// transitionBuilder: (context, anim1, anim2, child) {
|
||||||
|
// return SlideTransition(
|
||||||
|
// position: Tween(begin: const Offset(0, 1), end: const Offset(0, 0)).animate(
|
||||||
|
// CurvedAnimation(parent: anim1, curve: Curves.easeInOutCubicEmphasized),
|
||||||
|
// ),
|
||||||
|
// child: child,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// pageBuilder: (context, animation, secondaryAnimation) => AddBookmarkModal(fullscreen: width <= 700),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: NestedScrollView(
|
||||||
|
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||||
|
SliverOverlapAbsorber(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
|
sliver: SliverAppBar.large(
|
||||||
|
pinned: true,
|
||||||
|
floating: true,
|
||||||
|
centerTitle: false,
|
||||||
|
forceElevated: innerBoxIsScrolled,
|
||||||
|
title: Text(t.tags.tags),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
body: SafeArea(
|
||||||
|
top: false,
|
||||||
|
bottom: false,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) => RefreshIndicator(
|
||||||
|
displacement: 120,
|
||||||
|
onRefresh: () => ref.refresh(tagsRequestProvider.future),
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverOverlapInjector(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
|
),
|
||||||
|
if (tags.isLoading && !tags.isRefreshing)
|
||||||
|
const SliverFillRemaining(
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
if (tags.value != null && tags.value!.successful == false)
|
||||||
|
SliverFillRemaining(
|
||||||
|
child: ErrorScreen(
|
||||||
|
error: t.bookmarks.cannotLoadBookmarks,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (tags.value != null && tags.value!.successful == true && tags.value!.content!.results!.isEmpty)
|
||||||
|
SliverFillRemaining(
|
||||||
|
child: NoDataScreen(
|
||||||
|
message: t.bookmarks.noBookmarksAdded,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (tags.value != null && tags.value!.successful == true && tags.value!.content!.results!.isNotEmpty)
|
||||||
|
SliverList.builder(
|
||||||
|
itemCount: tags.value!.content!.results!.length + 1,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
// index == bookmarks.value!.content!.results!.length -> itemCount + 1
|
||||||
|
if (index == tags.value!.content!.results!.length) {
|
||||||
|
// Bottom gap for FAB
|
||||||
|
return const SizedBox(height: 80);
|
||||||
|
}
|
||||||
|
final tag = tags.value?.content?.results?[index];
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0),
|
||||||
|
dense: true,
|
||||||
|
title: Text(
|
||||||
|
tag!.name!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
dateToString(tag.dateAdded!),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (index < tags.value!.content!.results!.length - 1)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Divider(
|
||||||
|
color: Theme.of(context).colorScheme.tertiary.withOpacity(0.3),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: openAddModal,
|
||||||
|
child: const Icon(Icons.add_rounded),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user