|
@@ -2,62 +2,48 @@
|
|
|
|
|
|
import 'dart:async';
|
|
|
import 'dart:io';
|
|
|
-import 'dart:ui';
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/scheduler.dart';
|
|
|
import 'package:flutter/services.dart';
|
|
|
import 'package:logging/logging.dart';
|
|
|
import 'package:move_to_background/move_to_background.dart';
|
|
|
-import 'package:photo_manager/photo_manager.dart';
|
|
|
import 'package:photos/core/configuration.dart';
|
|
|
import 'package:photos/core/event_bus.dart';
|
|
|
-import 'package:photos/db/files_db.dart';
|
|
|
import 'package:photos/ente_theme_data.dart';
|
|
|
import 'package:photos/events/account_configured_event.dart';
|
|
|
import 'package:photos/events/backup_folders_updated_event.dart';
|
|
|
-import 'package:photos/events/files_updated_event.dart';
|
|
|
-import 'package:photos/events/force_reload_home_gallery_event.dart';
|
|
|
-import 'package:photos/events/local_photos_updated_event.dart';
|
|
|
import 'package:photos/events/permission_granted_event.dart';
|
|
|
import 'package:photos/events/subscription_purchased_event.dart';
|
|
|
import 'package:photos/events/sync_status_update_event.dart';
|
|
|
import 'package:photos/events/tab_changed_event.dart';
|
|
|
import 'package:photos/events/trigger_logout_event.dart';
|
|
|
import 'package:photos/events/user_logged_out_event.dart';
|
|
|
-import 'package:photos/models/file_load_result.dart';
|
|
|
import 'package:photos/models/gallery_type.dart';
|
|
|
import 'package:photos/models/selected_files.dart';
|
|
|
import 'package:photos/services/collections_service.dart';
|
|
|
-import 'package:photos/services/ignored_files_service.dart';
|
|
|
import 'package:photos/services/local_sync_service.dart';
|
|
|
import 'package:photos/services/update_service.dart';
|
|
|
import 'package:photos/services/user_service.dart';
|
|
|
import 'package:photos/states/user_details_state.dart';
|
|
|
-import 'package:photos/theme/colors.dart';
|
|
|
-import 'package:photos/theme/effects.dart';
|
|
|
import 'package:photos/theme/ente_theme.dart';
|
|
|
-import 'package:photos/ui/backup_folder_selection_page.dart';
|
|
|
import 'package:photos/ui/collections_gallery_widget.dart';
|
|
|
import 'package:photos/ui/common/bottom_shadow.dart';
|
|
|
-import 'package:photos/ui/common/gradient_button.dart';
|
|
|
import 'package:photos/ui/create_collection_page.dart';
|
|
|
import 'package:photos/ui/extents_page_view.dart';
|
|
|
-import 'package:photos/ui/grant_permissions_widget.dart';
|
|
|
-import 'package:photos/ui/landing_page_widget.dart';
|
|
|
+import 'package:photos/ui/home/grant_permissions_widget.dart';
|
|
|
+import 'package:photos/ui/home/header_widget.dart';
|
|
|
+import 'package:photos/ui/home/home_bottom_nav_bar.dart';
|
|
|
+import 'package:photos/ui/home/home_gallery_widget.dart';
|
|
|
+import 'package:photos/ui/home/landing_page_widget.dart';
|
|
|
+import 'package:photos/ui/home/preserve_footer_widget.dart';
|
|
|
+import 'package:photos/ui/home/start_backup_hook_widget.dart';
|
|
|
import 'package:photos/ui/loading_photos_widget.dart';
|
|
|
-import 'package:photos/ui/memories_widget.dart';
|
|
|
-import 'package:photos/ui/nav_bar.dart';
|
|
|
import 'package:photos/ui/settings/app_update_dialog.dart';
|
|
|
import 'package:photos/ui/settings_page.dart';
|
|
|
import 'package:photos/ui/shared_collections_gallery.dart';
|
|
|
-import 'package:photos/ui/status_bar_widget.dart';
|
|
|
-import 'package:photos/ui/viewer/gallery/gallery.dart';
|
|
|
-import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart';
|
|
|
-import 'package:photos/ui/viewer/gallery/gallery_footer_widget.dart';
|
|
|
import 'package:photos/ui/viewer/gallery/gallery_overlay_widget.dart';
|
|
|
import 'package:photos/utils/dialog_util.dart';
|
|
|
-import 'package:photos/utils/navigation_util.dart';
|
|
|
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
|
|
import 'package:uni_links/uni_links.dart';
|
|
|
|
|
@@ -81,7 +67,6 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
|
|
|
final PageController _pageController = PageController();
|
|
|
int _selectedTabIndex = 0;
|
|
|
- Widget _headerWidgetWithSettingsButton;
|
|
|
|
|
|
// for receiving media files
|
|
|
// ignore: unused_field
|
|
@@ -100,15 +85,14 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
@override
|
|
|
void initState() {
|
|
|
_logger.info("Building initstate");
|
|
|
- _headerWidgetWithSettingsButton = Stack(
|
|
|
- children: const [
|
|
|
- _headerWidget,
|
|
|
- ],
|
|
|
- );
|
|
|
_tabChangedEventSubscription =
|
|
|
Bus.instance.on<TabChangedEvent>().listen((event) {
|
|
|
if (event.source != TabChangedEventSource.pageView) {
|
|
|
+ debugPrint(
|
|
|
+ "TabChange going from $_selectedTabIndex to ${event.selectedIndex} souce: ${event.source}",
|
|
|
+ );
|
|
|
_selectedTabIndex = event.selectedIndex;
|
|
|
+ // _pageController.jumpToPage(_selectedTabIndex);
|
|
|
_pageController.animateToPage(
|
|
|
event.selectedIndex,
|
|
|
duration: const Duration(milliseconds: 100),
|
|
@@ -126,34 +110,7 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
});
|
|
|
_triggerLogoutEvent =
|
|
|
Bus.instance.on<TriggerLogoutEvent>().listen((event) async {
|
|
|
- final AlertDialog alert = AlertDialog(
|
|
|
- title: const Text("Session expired"),
|
|
|
- content: const Text("Please login again"),
|
|
|
- actions: [
|
|
|
- TextButton(
|
|
|
- child: Text(
|
|
|
- "Ok",
|
|
|
- style: TextStyle(
|
|
|
- color: Theme.of(context).colorScheme.greenAlternative,
|
|
|
- ),
|
|
|
- ),
|
|
|
- onPressed: () async {
|
|
|
- Navigator.of(context, rootNavigator: true).pop('dialog');
|
|
|
- final dialog = createProgressDialog(context, "Logging out...");
|
|
|
- await dialog.show();
|
|
|
- await Configuration.instance.logout();
|
|
|
- await dialog.hide();
|
|
|
- },
|
|
|
- ),
|
|
|
- ],
|
|
|
- );
|
|
|
-
|
|
|
- showDialog(
|
|
|
- context: context,
|
|
|
- builder: (BuildContext context) {
|
|
|
- return alert;
|
|
|
- },
|
|
|
- );
|
|
|
+ await _autoLogoutAlert();
|
|
|
});
|
|
|
_loggedOutEvent = Bus.instance.on<UserLoggedOutEvent>().listen((event) {
|
|
|
_logger.info('logged out, selectTab index to 0');
|
|
@@ -218,6 +175,37 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
super.initState();
|
|
|
}
|
|
|
|
|
|
+ Future<void> _autoLogoutAlert() async {
|
|
|
+ final AlertDialog alert = AlertDialog(
|
|
|
+ title: const Text("Session expired"),
|
|
|
+ content: const Text("Please login again"),
|
|
|
+ actions: [
|
|
|
+ TextButton(
|
|
|
+ child: Text(
|
|
|
+ "Ok",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Theme.of(context).colorScheme.greenAlternative,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ onPressed: () async {
|
|
|
+ Navigator.of(context, rootNavigator: true).pop('dialog');
|
|
|
+ final dialog = createProgressDialog(context, "Logging out...");
|
|
|
+ await dialog.show();
|
|
|
+ await Configuration.instance.logout();
|
|
|
+ await dialog.hide();
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+
|
|
|
+ await showDialog(
|
|
|
+ context: context,
|
|
|
+ builder: (BuildContext context) {
|
|
|
+ return alert;
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
@override
|
|
|
void dispose() {
|
|
|
_tabChangedEventSubscription.cancel();
|
|
@@ -262,8 +250,8 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
child: WillPopScope(
|
|
|
child: Scaffold(
|
|
|
drawerScrimColor: getEnteColorScheme(context).strokeFainter,
|
|
|
- drawerEnableOpenDragGesture:
|
|
|
- false, //using a hack instead of enabling this as enabling this will create other problems
|
|
|
+ drawerEnableOpenDragGesture: false,
|
|
|
+ //using a hack instead of enabling this as enabling this will create other problems
|
|
|
drawer: enableDrawer
|
|
|
? ConstrainedBox(
|
|
|
constraints: const BoxConstraints(maxWidth: 428),
|
|
@@ -345,8 +333,12 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
physics: const BouncingScrollPhysics(),
|
|
|
children: [
|
|
|
showBackupFolderHook
|
|
|
- ? _getBackupFolderSelectionHook()
|
|
|
- : _getMainGalleryWidget(),
|
|
|
+ ? const StartBackupHookWidget(headerWidget: _headerWidget)
|
|
|
+ : HomeGalleryWidget(
|
|
|
+ header: _headerWidget,
|
|
|
+ footer: const PreserveFooterWidget(),
|
|
|
+ selectedFiles: _selectedFiles,
|
|
|
+ ),
|
|
|
_deviceFolderGalleryWidget,
|
|
|
_sharedCollectionGallery,
|
|
|
],
|
|
@@ -422,347 +414,4 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|
|
final ott = Uri.parse(link).queryParameters["ott"];
|
|
|
UserService.instance.verifyEmail(context, ott);
|
|
|
}
|
|
|
-
|
|
|
- Widget _getMainGalleryWidget() {
|
|
|
- Widget header;
|
|
|
- if (_selectedFiles.files.isEmpty) {
|
|
|
- header = _headerWidgetWithSettingsButton;
|
|
|
- } else {
|
|
|
- header = _headerWidget;
|
|
|
- }
|
|
|
- final gallery = Gallery(
|
|
|
- asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) async {
|
|
|
- final ownerID = Configuration.instance.getUserID();
|
|
|
- final hasSelectedAllForBackup =
|
|
|
- Configuration.instance.hasSelectedAllFoldersForBackup();
|
|
|
- final archivedCollectionIds =
|
|
|
- CollectionsService.instance.getArchivedCollections();
|
|
|
- FileLoadResult result;
|
|
|
- if (hasSelectedAllForBackup) {
|
|
|
- result = await FilesDB.instance.getAllLocalAndUploadedFiles(
|
|
|
- creationStartTime,
|
|
|
- creationEndTime,
|
|
|
- ownerID,
|
|
|
- limit: limit,
|
|
|
- asc: asc,
|
|
|
- ignoredCollectionIDs: archivedCollectionIds,
|
|
|
- );
|
|
|
- } else {
|
|
|
- result = await FilesDB.instance.getAllPendingOrUploadedFiles(
|
|
|
- creationStartTime,
|
|
|
- creationEndTime,
|
|
|
- ownerID,
|
|
|
- limit: limit,
|
|
|
- asc: asc,
|
|
|
- ignoredCollectionIDs: archivedCollectionIds,
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- // hide ignored files from home page UI
|
|
|
- final ignoredIDs = await IgnoredFilesService.instance.ignoredIDs;
|
|
|
- result.files.removeWhere(
|
|
|
- (f) =>
|
|
|
- f.uploadedFileID == null &&
|
|
|
- IgnoredFilesService.instance.shouldSkipUpload(ignoredIDs, f),
|
|
|
- );
|
|
|
- return result;
|
|
|
- },
|
|
|
- reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
|
|
- removalEventTypes: const {
|
|
|
- EventType.deletedFromRemote,
|
|
|
- EventType.deletedFromEverywhere,
|
|
|
- EventType.archived,
|
|
|
- },
|
|
|
- forceReloadEvents: [
|
|
|
- Bus.instance.on<BackupFoldersUpdatedEvent>(),
|
|
|
- Bus.instance.on<ForceReloadHomeGalleryEvent>(),
|
|
|
- ],
|
|
|
- tagPrefix: "home_gallery",
|
|
|
- selectedFiles: _selectedFiles,
|
|
|
- header: header,
|
|
|
- footer: const GalleryFooterWidget(),
|
|
|
- );
|
|
|
- return Stack(
|
|
|
- children: [
|
|
|
- Container(
|
|
|
- child: gallery,
|
|
|
- ),
|
|
|
- HomePageAppBar(_selectedFiles),
|
|
|
- ],
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- Widget _getBackupFolderSelectionHook() {
|
|
|
- return Column(
|
|
|
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
- children: [
|
|
|
- _headerWidgetWithSettingsButton,
|
|
|
- Padding(
|
|
|
- padding: const EdgeInsets.only(top: 64),
|
|
|
- child: Image.asset(
|
|
|
- "assets/onboarding_safe.png",
|
|
|
- height: 206,
|
|
|
- ),
|
|
|
- ),
|
|
|
- Text(
|
|
|
- 'No photos are being backed up right now',
|
|
|
- style: Theme.of(context)
|
|
|
- .textTheme
|
|
|
- .caption
|
|
|
- .copyWith(fontFamily: 'Inter-Medium', fontSize: 16),
|
|
|
- ),
|
|
|
- Center(
|
|
|
- child: Material(
|
|
|
- type: MaterialType.transparency,
|
|
|
- child: Container(
|
|
|
- width: double.infinity,
|
|
|
- height: 64,
|
|
|
- padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
|
|
- child: GradientButton(
|
|
|
- onTap: () async {
|
|
|
- if (LocalSyncService.instance
|
|
|
- .hasGrantedLimitedPermissions()) {
|
|
|
- PhotoManager.presentLimited();
|
|
|
- } else {
|
|
|
- routeToPage(
|
|
|
- context,
|
|
|
- const BackupFolderSelectionPage(
|
|
|
- buttonText: "Start backup",
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
- },
|
|
|
- text: "Start backup",
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- const Padding(padding: EdgeInsets.all(50)),
|
|
|
- ],
|
|
|
- );
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class HomePageAppBar extends StatefulWidget {
|
|
|
- const HomePageAppBar(
|
|
|
- this.selectedFiles, {
|
|
|
- Key key,
|
|
|
- }) : super(key: key);
|
|
|
-
|
|
|
- final SelectedFiles selectedFiles;
|
|
|
-
|
|
|
- @override
|
|
|
- State<HomePageAppBar> createState() => _HomePageAppBarState();
|
|
|
-}
|
|
|
-
|
|
|
-class _HomePageAppBarState extends State<HomePageAppBar> {
|
|
|
- @override
|
|
|
- void initState() {
|
|
|
- super.initState();
|
|
|
- widget.selectedFiles.addListener(() {
|
|
|
- setState(() {});
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- final appBar = SizedBox(
|
|
|
- height: 60,
|
|
|
- child: GalleryAppBarWidget(
|
|
|
- GalleryType.homepage,
|
|
|
- null,
|
|
|
- widget.selectedFiles,
|
|
|
- ),
|
|
|
- );
|
|
|
- if (widget.selectedFiles.files.isEmpty) {
|
|
|
- return IgnorePointer(child: appBar);
|
|
|
- } else {
|
|
|
- return appBar;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class HomeBottomNavigationBar extends StatefulWidget {
|
|
|
- const HomeBottomNavigationBar(
|
|
|
- this.selectedFiles, {
|
|
|
- this.selectedTabIndex,
|
|
|
- Key key,
|
|
|
- }) : super(key: key);
|
|
|
-
|
|
|
- final SelectedFiles selectedFiles;
|
|
|
- final int selectedTabIndex;
|
|
|
-
|
|
|
- @override
|
|
|
- State<HomeBottomNavigationBar> createState() =>
|
|
|
- _HomeBottomNavigationBarState();
|
|
|
-}
|
|
|
-
|
|
|
-class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|
|
- StreamSubscription<TabChangedEvent> _tabChangedEventSubscription;
|
|
|
- int currentTabIndex = 0;
|
|
|
-
|
|
|
- @override
|
|
|
- void initState() {
|
|
|
- super.initState();
|
|
|
- currentTabIndex = widget.selectedTabIndex;
|
|
|
- widget.selectedFiles.addListener(() {
|
|
|
- setState(() {});
|
|
|
- });
|
|
|
- _tabChangedEventSubscription =
|
|
|
- Bus.instance.on<TabChangedEvent>().listen((event) {
|
|
|
- if (event.source != TabChangedEventSource.tabBar) {
|
|
|
- debugPrint('index changed to ${event.selectedIndex}');
|
|
|
- if (mounted) {
|
|
|
- setState(() {
|
|
|
- currentTabIndex = event.selectedIndex;
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- void dispose() {
|
|
|
- _tabChangedEventSubscription.cancel();
|
|
|
- super.dispose();
|
|
|
- }
|
|
|
-
|
|
|
- void _onTabChange(int index) {
|
|
|
- Bus.instance.fire(
|
|
|
- TabChangedEvent(
|
|
|
- index,
|
|
|
- TabChangedEventSource.tabBar,
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- final bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
|
|
- final enteColorScheme = getEnteColorScheme(context);
|
|
|
- final navBarBlur =
|
|
|
- MediaQuery.of(context).platformBrightness == Brightness.light
|
|
|
- ? blurBase
|
|
|
- : blurMuted;
|
|
|
-
|
|
|
- return AnimatedContainer(
|
|
|
- duration: const Duration(milliseconds: 300),
|
|
|
- curve: Curves.easeInOut,
|
|
|
- height: filesAreSelected ? 0 : 56,
|
|
|
- child: AnimatedOpacity(
|
|
|
- duration: const Duration(milliseconds: 100),
|
|
|
- opacity: filesAreSelected ? 0.0 : 1.0,
|
|
|
- curve: Curves.easeIn,
|
|
|
- child: IgnorePointer(
|
|
|
- ignoring: filesAreSelected,
|
|
|
- child: ListView(
|
|
|
- physics: const NeverScrollableScrollPhysics(),
|
|
|
- children: [
|
|
|
- Row(
|
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
|
- children: [
|
|
|
- ClipRRect(
|
|
|
- borderRadius: BorderRadius.circular(32),
|
|
|
- child: Container(
|
|
|
- alignment: Alignment.bottomCenter,
|
|
|
- height: 48,
|
|
|
- child: ClipRect(
|
|
|
- child: BackdropFilter(
|
|
|
- filter: ImageFilter.blur(
|
|
|
- sigmaX: navBarBlur,
|
|
|
- sigmaY: navBarBlur,
|
|
|
- ),
|
|
|
- child: GNav(
|
|
|
- curve: Curves.easeOutExpo,
|
|
|
- backgroundColor:
|
|
|
- getEnteColorScheme(context).fillMuted,
|
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
|
- rippleColor: Colors.white.withOpacity(0.1),
|
|
|
- activeColor: Theme.of(context)
|
|
|
- .colorScheme
|
|
|
- .gNavBarActiveColor,
|
|
|
- iconSize: 24,
|
|
|
- padding: const EdgeInsets.fromLTRB(16, 6, 16, 6),
|
|
|
- duration: const Duration(milliseconds: 200),
|
|
|
- gap: 0,
|
|
|
- tabBorderRadius: 32,
|
|
|
- tabBackgroundColor: Theme.of(context)
|
|
|
- .colorScheme
|
|
|
- .gNavBarActiveColor,
|
|
|
- haptic: false,
|
|
|
- tabs: [
|
|
|
- GButton(
|
|
|
- margin: const EdgeInsets.fromLTRB(8, 6, 10, 6),
|
|
|
- icon: Icons.home_rounded,
|
|
|
- iconColor: enteColorScheme.tabIcon,
|
|
|
- iconActiveColor: strokeBaseLight,
|
|
|
- text: '',
|
|
|
- onPressed: () {
|
|
|
- _onTabChange(
|
|
|
- 0,
|
|
|
- ); // To take care of occasional missing events
|
|
|
- },
|
|
|
- ),
|
|
|
- GButton(
|
|
|
- margin: const EdgeInsets.fromLTRB(10, 6, 10, 6),
|
|
|
- icon: Icons.collections_rounded,
|
|
|
- iconColor: enteColorScheme.tabIcon,
|
|
|
- iconActiveColor: strokeBaseLight,
|
|
|
- text: '',
|
|
|
- onPressed: () {
|
|
|
- _onTabChange(
|
|
|
- 1,
|
|
|
- ); // To take care of occasional missing events
|
|
|
- },
|
|
|
- ),
|
|
|
- GButton(
|
|
|
- margin: const EdgeInsets.fromLTRB(10, 6, 8, 6),
|
|
|
- icon: Icons.people_outlined,
|
|
|
- iconColor: enteColorScheme.tabIcon,
|
|
|
- iconActiveColor: strokeBaseLight,
|
|
|
- text: '',
|
|
|
- onPressed: () {
|
|
|
- _onTabChange(
|
|
|
- 2,
|
|
|
- ); // To take care of occasional missing events
|
|
|
- },
|
|
|
- ),
|
|
|
- ],
|
|
|
- selectedIndex: currentTabIndex,
|
|
|
- onTabChange: _onTabChange,
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- ],
|
|
|
- ),
|
|
|
- ],
|
|
|
- ),
|
|
|
- ),
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class HeaderWidget extends StatelessWidget {
|
|
|
- static const _memoriesWidget = MemoriesWidget();
|
|
|
- static const _statusBarWidget = StatusBarWidget();
|
|
|
-
|
|
|
- const HeaderWidget({
|
|
|
- Key key,
|
|
|
- }) : super(key: key);
|
|
|
-
|
|
|
- @override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- Logger("Header").info("Building header widget");
|
|
|
- const list = [
|
|
|
- _statusBarWidget,
|
|
|
- _memoriesWidget,
|
|
|
- ];
|
|
|
- return Column(
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
- children: list,
|
|
|
- );
|
|
|
- }
|
|
|
}
|