From f1a5118e4717f0fef2b6ad2d111914ac01dc8abd Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Fri, 26 May 2023 17:54:03 +0530 Subject: [PATCH] Refactor --- lib/ui/tools/collage/collage_item_widget.dart | 27 ++ lib/ui/tools/collage/create_collage_page.dart | 159 +++++++ .../collage/create_collage_page_two.dart | 209 +++++++++ .../tools/collage/outlined_tile_widget.dart | 26 ++ lib/ui/tools/create_collage_page.dart | 407 ------------------ .../file_selection_actions_widget.dart | 2 +- 6 files changed, 422 insertions(+), 408 deletions(-) create mode 100644 lib/ui/tools/collage/collage_item_widget.dart create mode 100644 lib/ui/tools/collage/create_collage_page.dart create mode 100644 lib/ui/tools/collage/create_collage_page_two.dart create mode 100644 lib/ui/tools/collage/outlined_tile_widget.dart delete mode 100644 lib/ui/tools/create_collage_page.dart diff --git a/lib/ui/tools/collage/collage_item_widget.dart b/lib/ui/tools/collage/collage_item_widget.dart new file mode 100644 index 000000000..095bb0c0b --- /dev/null +++ b/lib/ui/tools/collage/collage_item_widget.dart @@ -0,0 +1,27 @@ + +import "package:flutter/material.dart"; +import "package:photos/models/file.dart"; +import "package:photos/ui/viewer/file/zoomable_image.dart"; + +class CollageItemWidget extends StatelessWidget { + const CollageItemWidget( + this.file, { + super.key, + }); + + final File file; + + @override + Widget build(BuildContext context) { + return InteractiveViewer( + child: ZoomableImage( + file, + backgroundDecoration: const BoxDecoration( + color: Colors.transparent, + ), + tagPrefix: "collage_", + shouldCover: true, + ), + ); + } +} diff --git a/lib/ui/tools/collage/create_collage_page.dart b/lib/ui/tools/collage/create_collage_page.dart new file mode 100644 index 000000000..c669947c7 --- /dev/null +++ b/lib/ui/tools/collage/create_collage_page.dart @@ -0,0 +1,159 @@ +import "package:flutter/material.dart"; +import "package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart"; +import "package:logging/logging.dart"; +import "package:photo_manager/photo_manager.dart"; +import "package:photos/core/event_bus.dart"; +import "package:photos/db/files_db.dart"; +import "package:photos/events/local_photos_updated_event.dart"; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/file.dart"; +import "package:photos/services/sync_service.dart"; +import "package:photos/ui/components/buttons/button_widget.dart"; +import "package:photos/ui/components/models/button_type.dart"; +import "package:photos/ui/tools/collage/create_collage_page_two.dart"; +import "package:photos/ui/viewer/file/detail_page.dart"; +import "package:photos/utils/navigation_util.dart"; +import "package:photos/utils/toast_util.dart"; +import "package:widgets_to_image/widgets_to_image.dart"; + +class CreateCollagePage extends StatefulWidget { + final List files; + + const CreateCollagePage(this.files, {super.key}); + + @override + State createState() => _CreateCollagePageState(); +} + +class _CreateCollagePageState extends State { + final _logger = Logger("CreateCollagePage"); + final _widgetsToImageController = WidgetsToImageController(); + + @override + Widget build(BuildContext context) { + for (final file in widget.files) { + _logger.info(file.displayName); + } + return Scaffold( + appBar: AppBar( + elevation: 0, + title: Text(S.of(context).createCollage), + ), + body: _getBody(), + ); + } + + Widget _getBody() { + final count = widget.files.length; + + return Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + count == 2 + ? TwoImageCollageCreator( + widget.files[0], + widget.files[1], + _widgetsToImageController, + ) + : _getGrid(), + const SizedBox( + height: 24, + ), + ButtonWidget( + buttonType: ButtonType.neutral, + labelText: S.of(context).saveCollage, + onTap: _onSaveClicked, + shouldSurfaceExecutionStates: true, + ), + ], + ), + ); + } + + Future _onSaveClicked() async { + final bytes = await _widgetsToImageController.capture(); + final fileName = "ente_collage_" + + DateTime.now().microsecondsSinceEpoch.toString() + + ".jpeg"; + //Disabling notifications for assets changing to insert the file into + //files db before triggering a sync. + PhotoManager.stopChangeNotify(); + final AssetEntity? newAsset = + await (PhotoManager.editor.saveImage(bytes!, title: fileName)); + final newFile = await File.fromAsset('', newAsset!); + newFile.generatedID = await FilesDB.instance.insert(newFile); + Bus.instance + .fire(LocalPhotosUpdatedEvent([newFile], source: "collageSave")); + SyncService.instance.sync(); + showShortToast(context, S.of(context).collageSaved); + replacePage( + context, + DetailPage( + DetailPageConfiguration([newFile], null, 0, "collage"), + ), + ); + } + + Widget _getGrid() { + return const TestGrid(); + } +} + + +class Tile extends StatelessWidget { + final String text; + const Tile(this.text, {super.key}); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.blue, + child: Center(child: Text(text)), + ); + } +} + +class TestGrid extends StatelessWidget { + const TestGrid({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return StaggeredGrid.count( + crossAxisCount: 2, + mainAxisSpacing: 4, + crossAxisSpacing: 4, + axisDirection: AxisDirection.down, + children: const [ + StaggeredGridTile.count( + crossAxisCellCount: 2, + mainAxisCellCount: 1, + child: Tile("0"), + ), + StaggeredGridTile.count( + crossAxisCellCount: 2, + mainAxisCellCount: 1, + child: Tile("1"), + ), + // StaggeredGridTile.count( + // crossAxisCellCount: 1, + // mainAxisCellCount: 1, + // child: Tile("2"), + // ), + // StaggeredGridTile.count( + // crossAxisCellCount: 1, + // mainAxisCellCount: 1, + // child: Tile("3"), + // ), + // StaggeredGridTile.count( + // crossAxisCellCount: 4, + // mainAxisCellCount: 2, + // child: Tile("4"), + // ), + ], + ); + } +} + diff --git a/lib/ui/tools/collage/create_collage_page_two.dart b/lib/ui/tools/collage/create_collage_page_two.dart new file mode 100644 index 000000000..661ed2086 --- /dev/null +++ b/lib/ui/tools/collage/create_collage_page_two.dart @@ -0,0 +1,209 @@ +import "package:flutter/widgets.dart"; +import "package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart"; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/file.dart"; +import "package:photos/ui/tools/collage/collage_item_widget.dart"; +import "package:photos/ui/tools/collage/outlined_tile_widget.dart"; +import "package:widgets_to_image/widgets_to_image.dart"; + +class TwoImageCollageCreator extends StatefulWidget { + const TwoImageCollageCreator( + this.first, + this.second, + this.controller, { + super.key, + }); + + final File first, second; + final WidgetsToImageController controller; + + @override + State createState() => _TwoImageCollageCreatorState(); +} + +class _TwoImageCollageCreatorState extends State { + bool _isLayoutVertical = false; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + WidgetsToImage( + controller: widget.controller, + child: _getCollage(), + ), + Padding( + padding: const EdgeInsets.fromLTRB(8, 20, 0, 4), + child: Text(S.of(context).collageLayout), + ), + Row( + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.all(4), + child: HorizontalSplitIcon( + isActive: !_isLayoutVertical, + ), + ), + onTap: () { + setState(() { + _isLayoutVertical = false; + }); + }, + ), + const Padding(padding: EdgeInsets.all(2)), + GestureDetector( + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.all(4), + child: VerticalSplitIcon( + isActive: _isLayoutVertical, + ), + ), + onTap: () { + setState(() { + _isLayoutVertical = true; + }); + }, + ), + ], + ), + ], + ); + } + + Widget _getCollage() { + return _isLayoutVertical + ? VerticalSplit( + CollageItemWidget(widget.first), + CollageItemWidget(widget.second), + ) + : HorizontalSplit( + CollageItemWidget(widget.first), + CollageItemWidget(widget.second), + ); + } +} + +class VerticalSplit extends StatelessWidget { + const VerticalSplit( + this.first, + this.second, { + super.key, + this.mainAxisSpacing = 4, + this.crossAxisSpacing = 4, + }); + + final Widget first, second; + final double mainAxisSpacing, crossAxisSpacing; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(4), + child: StaggeredGrid.count( + crossAxisCount: 2, + mainAxisSpacing: mainAxisSpacing, + crossAxisSpacing: crossAxisSpacing, + axisDirection: AxisDirection.down, + children: [ + StaggeredGridTile.count( + crossAxisCellCount: 1, + mainAxisCellCount: 2, + child: first, + ), + StaggeredGridTile.count( + crossAxisCellCount: 1, + mainAxisCellCount: 2, + child: second, + ), + ], + ), + ); + } +} + +class HorizontalSplit extends StatelessWidget { + const HorizontalSplit( + this.first, + this.second, { + super.key, + this.mainAxisSpacing = 4, + this.crossAxisSpacing = 4, + }); + + final Widget first, second; + final double mainAxisSpacing, crossAxisSpacing; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(4), + child: StaggeredGrid.count( + crossAxisCount: 2, + mainAxisSpacing: mainAxisSpacing, + crossAxisSpacing: crossAxisSpacing, + axisDirection: AxisDirection.down, + children: [ + StaggeredGridTile.count( + crossAxisCellCount: 2, + mainAxisCellCount: 1, + child: first, + ), + StaggeredGridTile.count( + crossAxisCellCount: 2, + mainAxisCellCount: 1, + child: second, + ), + ], + ), + ); + } +} + +class VerticalSplitIcon extends StatelessWidget { + const VerticalSplitIcon({ + super.key, + this.isActive = false, + }); + + final bool isActive; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 36, + height: 36, + child: VerticalSplit( + OutlinedTile(isActive: isActive), + OutlinedTile(isActive: isActive), + mainAxisSpacing: 2, + crossAxisSpacing: 2, + ), + ); + } +} + +class HorizontalSplitIcon extends StatelessWidget { + const HorizontalSplitIcon({ + super.key, + this.isActive = false, + }); + final bool isActive; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 36, + height: 36, + child: HorizontalSplit( + OutlinedTile(isActive: isActive), + OutlinedTile(isActive: isActive), + mainAxisSpacing: 2, + crossAxisSpacing: 2, + ), + ); + } +} diff --git a/lib/ui/tools/collage/outlined_tile_widget.dart b/lib/ui/tools/collage/outlined_tile_widget.dart new file mode 100644 index 000000000..c03421428 --- /dev/null +++ b/lib/ui/tools/collage/outlined_tile_widget.dart @@ -0,0 +1,26 @@ +import "package:flutter/widgets.dart"; +import "package:photos/theme/ente_theme.dart"; + +class OutlinedTile extends StatelessWidget { + const OutlinedTile({ + super.key, + this.isActive = false, + }); + + final bool isActive; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border.all( + color: isActive + ? getEnteColorScheme(context).strokeBase + : getEnteColorScheme(context).strokeMuted, + width: 2, + ), + borderRadius: const BorderRadius.all(Radius.circular(2)), + ), + ); + } +} diff --git a/lib/ui/tools/create_collage_page.dart b/lib/ui/tools/create_collage_page.dart deleted file mode 100644 index 8f57ee0d0..000000000 --- a/lib/ui/tools/create_collage_page.dart +++ /dev/null @@ -1,407 +0,0 @@ -import "package:flutter/material.dart"; -import "package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart"; -import "package:logging/logging.dart"; -import "package:photo_manager/photo_manager.dart"; -import "package:photos/core/event_bus.dart"; -import "package:photos/db/files_db.dart"; -import "package:photos/events/local_photos_updated_event.dart"; -import "package:photos/generated/l10n.dart"; -import "package:photos/models/file.dart"; -import "package:photos/services/sync_service.dart"; -import "package:photos/theme/ente_theme.dart"; -import "package:photos/ui/components/buttons/button_widget.dart"; -import "package:photos/ui/components/models/button_type.dart"; -import "package:photos/ui/viewer/file/detail_page.dart"; -import "package:photos/ui/viewer/file/zoomable_image.dart"; -import "package:photos/utils/navigation_util.dart"; -import "package:photos/utils/toast_util.dart"; -import "package:widgets_to_image/widgets_to_image.dart"; - -class CreateCollagePage extends StatefulWidget { - final List files; - - const CreateCollagePage(this.files, {super.key}); - - @override - State createState() => _CreateCollagePageState(); -} - -class _CreateCollagePageState extends State { - final _logger = Logger("CreateCollagePage"); - final _widgetsToImageController = WidgetsToImageController(); - - @override - Widget build(BuildContext context) { - for (final file in widget.files) { - _logger.info(file.displayName); - } - return Scaffold( - appBar: AppBar( - elevation: 0, - title: Text(S.of(context).createCollage), - ), - body: _getBody(), - ); - } - - Widget _getBody() { - final count = widget.files.length; - - return Padding( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - count == 2 - ? TwoImageCollageCreator( - widget.files[0], - widget.files[1], - _widgetsToImageController, - ) - : _getGrid(), - const SizedBox( - height: 24, - ), - ButtonWidget( - buttonType: ButtonType.neutral, - labelText: S.of(context).saveCollage, - onTap: _onSaveClicked, - shouldSurfaceExecutionStates: true, - ), - ], - ), - ); - } - - Future _onSaveClicked() async { - final bytes = await _widgetsToImageController.capture(); - final fileName = "ente_collage_" + - DateTime.now().microsecondsSinceEpoch.toString() + - ".jpeg"; - //Disabling notifications for assets changing to insert the file into - //files db before triggering a sync. - PhotoManager.stopChangeNotify(); - final AssetEntity? newAsset = - await (PhotoManager.editor.saveImage(bytes!, title: fileName)); - final newFile = await File.fromAsset('', newAsset!); - newFile.generatedID = await FilesDB.instance.insert(newFile); - Bus.instance - .fire(LocalPhotosUpdatedEvent([newFile], source: "collageSave")); - SyncService.instance.sync(); - showShortToast(context, S.of(context).collageSaved); - replacePage( - context, - DetailPage( - DetailPageConfiguration([newFile], null, 0, "collage"), - ), - ); - } - - Widget _getGrid() { - return const TestGrid(); - } -} - -class TwoImageCollageCreator extends StatefulWidget { - const TwoImageCollageCreator( - this.first, - this.second, - this.controller, { - super.key, - }); - - final File first, second; - final WidgetsToImageController controller; - - @override - State createState() => _TwoImageCollageCreatorState(); -} - -class _TwoImageCollageCreatorState extends State { - bool _isLayoutVertical = false; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - WidgetsToImage( - controller: widget.controller, - child: _getCollage(), - ), - Padding( - padding: const EdgeInsets.fromLTRB(8, 20, 0, 4), - child: Text(S.of(context).collageLayout), - ), - Row( - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - child: Padding( - padding: const EdgeInsets.all(4), - child: HorizontalSplitIcon( - isActive: !_isLayoutVertical, - ), - ), - onTap: () { - setState(() { - _isLayoutVertical = false; - }); - }, - ), - const Padding(padding: EdgeInsets.all(2)), - GestureDetector( - behavior: HitTestBehavior.opaque, - child: Padding( - padding: const EdgeInsets.all(4), - child: VerticalSplitIcon( - isActive: _isLayoutVertical, - ), - ), - onTap: () { - setState(() { - _isLayoutVertical = true; - }); - }, - ), - ], - ), - ], - ); - } - - Widget _getCollage() { - return _isLayoutVertical - ? VerticalSplit( - CollageItemWidget(widget.first), - CollageItemWidget(widget.second), - ) - : HorizontalSplit( - CollageItemWidget(widget.first), - CollageItemWidget(widget.second), - ); - } -} - -class VerticalSplit extends StatelessWidget { - const VerticalSplit( - this.first, - this.second, { - super.key, - this.mainAxisSpacing = 4, - this.crossAxisSpacing = 4, - }); - - final Widget first, second; - final double mainAxisSpacing, crossAxisSpacing; - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(4), - child: StaggeredGrid.count( - crossAxisCount: 2, - mainAxisSpacing: mainAxisSpacing, - crossAxisSpacing: crossAxisSpacing, - axisDirection: AxisDirection.down, - children: [ - StaggeredGridTile.count( - crossAxisCellCount: 1, - mainAxisCellCount: 2, - child: first, - ), - StaggeredGridTile.count( - crossAxisCellCount: 1, - mainAxisCellCount: 2, - child: second, - ), - ], - ), - ); - } -} - -class HorizontalSplit extends StatelessWidget { - const HorizontalSplit( - this.first, - this.second, { - super.key, - this.mainAxisSpacing = 4, - this.crossAxisSpacing = 4, - }); - - final Widget first, second; - final double mainAxisSpacing, crossAxisSpacing; - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(4), - child: StaggeredGrid.count( - crossAxisCount: 2, - mainAxisSpacing: mainAxisSpacing, - crossAxisSpacing: crossAxisSpacing, - axisDirection: AxisDirection.down, - children: [ - StaggeredGridTile.count( - crossAxisCellCount: 2, - mainAxisCellCount: 1, - child: first, - ), - StaggeredGridTile.count( - crossAxisCellCount: 2, - mainAxisCellCount: 1, - child: second, - ), - ], - ), - ); - } -} - -class CollageItemWidget extends StatelessWidget { - const CollageItemWidget( - this.file, { - super.key, - }); - - final File file; - - @override - Widget build(BuildContext context) { - return InteractiveViewer( - child: ZoomableImage( - file, - backgroundDecoration: const BoxDecoration( - color: Colors.transparent, - ), - tagPrefix: "collage_", - shouldCover: true, - ), - ); - } -} - -class Tile extends StatelessWidget { - final String text; - const Tile(this.text, {super.key}); - - @override - Widget build(BuildContext context) { - return Container( - color: Colors.blue, - child: Center(child: Text(text)), - ); - } -} - -class TestGrid extends StatelessWidget { - const TestGrid({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return StaggeredGrid.count( - crossAxisCount: 2, - mainAxisSpacing: 4, - crossAxisSpacing: 4, - axisDirection: AxisDirection.down, - children: const [ - StaggeredGridTile.count( - crossAxisCellCount: 2, - mainAxisCellCount: 1, - child: Tile("0"), - ), - StaggeredGridTile.count( - crossAxisCellCount: 2, - mainAxisCellCount: 1, - child: Tile("1"), - ), - // StaggeredGridTile.count( - // crossAxisCellCount: 1, - // mainAxisCellCount: 1, - // child: Tile("2"), - // ), - // StaggeredGridTile.count( - // crossAxisCellCount: 1, - // mainAxisCellCount: 1, - // child: Tile("3"), - // ), - // StaggeredGridTile.count( - // crossAxisCellCount: 4, - // mainAxisCellCount: 2, - // child: Tile("4"), - // ), - ], - ); - } -} - -class VerticalSplitIcon extends StatelessWidget { - const VerticalSplitIcon({ - super.key, - this.isActive = false, - }); - - final bool isActive; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 36, - height: 36, - child: VerticalSplit( - OutlinedTile(isActive: isActive), - OutlinedTile(isActive: isActive), - mainAxisSpacing: 2, - crossAxisSpacing: 2, - ), - ); - } -} - -class HorizontalSplitIcon extends StatelessWidget { - const HorizontalSplitIcon({ - super.key, - this.isActive = false, - }); - final bool isActive; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 36, - height: 36, - child: HorizontalSplit( - OutlinedTile(isActive: isActive), - OutlinedTile(isActive: isActive), - mainAxisSpacing: 2, - crossAxisSpacing: 2, - ), - ); - } -} - -class OutlinedTile extends StatelessWidget { - const OutlinedTile({ - super.key, - this.isActive = false, - }); - - final bool isActive; - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - border: Border.all( - color: isActive - ? getEnteColorScheme(context).strokeBase - : getEnteColorScheme(context).strokeMuted, - width: 2, - ), - borderRadius: const BorderRadius.all(Radius.circular(2)), - ), - ); - } -} diff --git a/lib/ui/viewer/actions/file_selection_actions_widget.dart b/lib/ui/viewer/actions/file_selection_actions_widget.dart index ef495708d..74527af0e 100644 --- a/lib/ui/viewer/actions/file_selection_actions_widget.dart +++ b/lib/ui/viewer/actions/file_selection_actions_widget.dart @@ -23,7 +23,7 @@ import 'package:photos/ui/components/bottom_action_bar/expanded_menu_widget.dart import 'package:photos/ui/components/buttons/button_widget.dart'; import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/ui/sharing/manage_links_widget.dart'; -import "package:photos/ui/tools/create_collage_page.dart"; +import 'package:photos/ui/tools/collage/create_collage_page.dart'; import 'package:photos/utils/delete_file_util.dart'; import 'package:photos/utils/magic_util.dart'; import 'package:photos/utils/navigation_util.dart';