diff --git a/app/lib/dialogs/import/add.dart b/app/lib/dialogs/import/add.dart index f62d2163e2df..efec645ea8c9 100644 --- a/app/lib/dialogs/import/add.dart +++ b/app/lib/dialogs/import/add.dart @@ -84,227 +84,232 @@ class _AddDialogState extends State { ); } - return LayoutBuilder( - builder: (context, constraints) => ResponsiveDialog( - constraints: const BoxConstraints( - maxWidth: 1000, - ), - child: Column(mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton.outlined( - onPressed: () => Navigator.of(context).pop(), - icon: const PhosphorIcon(PhosphorIconsLight.x), - tooltip: AppLocalizations.of(context).close, - ), - const SizedBox(width: 16), - Text( - AppLocalizations.of(context).add, - style: Theme.of(context).textTheme.headlineSmall, - ), - const SizedBox(width: 8), - Expanded( - child: Align( - child: SearchBar( - autoFocus: true, - constraints: - const BoxConstraints(maxWidth: 200, minHeight: 50), - leading: - const PhosphorIcon(PhosphorIconsLight.magnifyingGlass), - hintText: AppLocalizations.of(context).search, - controller: _searchController, + return SafeArea( + child: LayoutBuilder( + builder: (context, constraints) => ResponsiveDialog( + constraints: const BoxConstraints( + maxWidth: 1000, + ), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton.outlined( + onPressed: () => Navigator.of(context).pop(), + icon: const PhosphorIcon(PhosphorIconsLight.x), + tooltip: AppLocalizations.of(context).close, ), - )), - const SizedBox(width: 8), - IconButton( - onPressed: () => openHelp(['add']), - icon: const PhosphorIcon(PhosphorIconsLight.sealQuestion), - tooltip: AppLocalizations.of(context).help, - ), - ], + const SizedBox(width: 16), + Text( + AppLocalizations.of(context).add, + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(width: 8), + Expanded( + child: Align( + child: SearchBar( + autoFocus: true, + constraints: + const BoxConstraints(maxWidth: 200, minHeight: 50), + leading: const PhosphorIcon( + PhosphorIconsLight.magnifyingGlass), + hintText: AppLocalizations.of(context).search, + controller: _searchController, + ), + )), + const SizedBox(width: 8), + IconButton( + onPressed: () => openHelp(['add']), + icon: const PhosphorIcon(PhosphorIconsLight.sealQuestion), + tooltip: AppLocalizations.of(context).help, + ), + ], + ), ), - ), - const SizedBox(height: 8), - Flexible( - child: Material( - type: MaterialType.transparency, - child: ValueListenableBuilder( - valueListenable: _searchController, - builder: (context, value, _) => FutureBuilder>( - future: Future.wait(ImportType.values - .map((e) async => (e, await e.isAvailable()))) - .then((value) => - value.where((e) => e.$2).map((e) => e.$1).toList()), - builder: (context, snapshot) { - final isMobile = - constraints.maxWidth < LeapBreakpoints.compact; - final search = value.text; - final imports = (snapshot.data ?? []) - .where((e) => e - .getLocalizedName(context) - .toLowerCase() - .contains(search.toLowerCase())) - .toList(); - final tools = [ - Tool.hand, - () => Tool.select(mode: SelectMode.lasso), - () => Tool.select(mode: SelectMode.rectangle), - Tool.pen, - Tool.stamp, - Tool.laser, - Tool.pathEraser, - Tool.label, - Tool.eraser, - Tool.area, - Tool.presentation, - () => Tool.spacer(axis: Axis2D.vertical), - () => Tool.spacer(axis: Axis2D.horizontal), - Tool.eyeDropper, - ] - .map((e) => e()) - .where((e) => e - .getLocalizedName(context) - .toLowerCase() - .contains(search.toLowerCase())) - .toList(); - final shapes = [ - PathShape.circle, - PathShape.rectangle, - PathShape.line, - PathShape.triangle, - ] - .map((e) => e()) - .where((e) => e - .getLocalizedName(context) - .toLowerCase() - .contains(search.toLowerCase())) - .toList(); - final textures = [SurfaceTexture.pattern] - .map((e) => e()) - .where((e) => e - .getLocalizedName(context) - .toLowerCase() - .contains(search.toLowerCase())) - .toList(); - final actions = [ - Tool.undo, - Tool.redo, - Tool.fullScreen, - Tool.collection, - ] - .map((e) => e()) - .where((e) => e - .getLocalizedName(context) - .toLowerCase() - .contains(search.toLowerCase())) - .toList(); - return ListView( - shrinkWrap: true, - children: [ - if (imports.isNotEmpty) ...[ - _ToolsListView( - isMobile: isMobile, - title: AppLocalizations.of(context).import, - children: imports - .map( - (e) => BoxTile( - title: Text( - e.getLocalizedName(context), - textAlign: TextAlign.center, - ), - trailing: IconButton( - onPressed: () => - addTool(Tool.asset(importType: e)), - tooltip: - AppLocalizations.of(context).pin, - icon: const PhosphorIcon( - PhosphorIconsLight.pushPin), + const SizedBox(height: 8), + Flexible( + child: Material( + type: MaterialType.transparency, + child: ValueListenableBuilder( + valueListenable: _searchController, + builder: (context, value, _) => FutureBuilder< + List>( + future: Future.wait(ImportType.values + .map((e) async => (e, await e.isAvailable()))) + .then((value) => value + .where((e) => e.$2) + .map((e) => e.$1) + .toList()), + builder: (context, snapshot) { + final isMobile = + constraints.maxWidth < LeapBreakpoints.compact; + final search = value.text; + final imports = (snapshot.data ?? []) + .where((e) => e + .getLocalizedName(context) + .toLowerCase() + .contains(search.toLowerCase())) + .toList(); + final tools = [ + Tool.hand, + () => Tool.select(mode: SelectMode.lasso), + () => Tool.select(mode: SelectMode.rectangle), + Tool.pen, + Tool.stamp, + Tool.laser, + Tool.pathEraser, + Tool.label, + Tool.eraser, + Tool.area, + Tool.presentation, + () => Tool.spacer(axis: Axis2D.vertical), + () => Tool.spacer(axis: Axis2D.horizontal), + Tool.eyeDropper, + ] + .map((e) => e()) + .where((e) => e + .getLocalizedName(context) + .toLowerCase() + .contains(search.toLowerCase())) + .toList(); + final shapes = [ + PathShape.circle, + PathShape.rectangle, + PathShape.line, + PathShape.triangle, + ] + .map((e) => e()) + .where((e) => e + .getLocalizedName(context) + .toLowerCase() + .contains(search.toLowerCase())) + .toList(); + final textures = [SurfaceTexture.pattern] + .map((e) => e()) + .where((e) => e + .getLocalizedName(context) + .toLowerCase() + .contains(search.toLowerCase())) + .toList(); + final actions = [ + Tool.undo, + Tool.redo, + Tool.fullScreen, + Tool.collection, + ] + .map((e) => e()) + .where((e) => e + .getLocalizedName(context) + .toLowerCase() + .contains(search.toLowerCase())) + .toList(); + return ListView( + shrinkWrap: true, + children: [ + if (imports.isNotEmpty) ...[ + _ToolsListView( + isMobile: isMobile, + title: AppLocalizations.of(context).import, + children: imports + .map( + (e) => BoxTile( + title: Text( + e.getLocalizedName(context), + textAlign: TextAlign.center, + ), + trailing: IconButton( + onPressed: () => addTool( + Tool.asset(importType: e)), + tooltip: + AppLocalizations.of(context).pin, + icon: const PhosphorIcon( + PhosphorIconsLight.pushPin), + ), + icon: PhosphorIcon( + e.icon(PhosphorIconsStyle.light)), + onTap: () async { + final bloc = + context.read(); + final importService = + context.read(); + Navigator.of(context).pop(); + await showImportAssetWizard( + e, context, bloc, importService); + }, ), - icon: PhosphorIcon( - e.icon(PhosphorIconsStyle.light)), - onTap: () async { - final bloc = - context.read(); - final importService = - context.read(); - Navigator.of(context).pop(); - await showImportAssetWizard( - e, context, bloc, importService); - }, - ), - ) - .toList(), - ), - const SizedBox(height: 16), - ], - if (tools.isEmpty && - shapes.isEmpty && - textures.isEmpty && - actions.isEmpty) - Padding( - padding: const EdgeInsets.symmetric( - vertical: 64, horizontal: 16), - child: Text( - AppLocalizations.of(context).noElements, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, + ) + .toList(), ), - ), - if (tools.isNotEmpty) ...[ - _ToolsListView( - isMobile: isMobile, - title: AppLocalizations.of(context).tools, - children: tools.map(buildTool).toList(), - ), - const SizedBox(height: 16), - ], - if (shapes.isNotEmpty || textures.isNotEmpty) ...[ - _ToolsListView( - isMobile: isMobile, - title: AppLocalizations.of(context).surface, - children: [ - ...shapes.map((e) => BoxTile( - title: Text( - e.getLocalizedName(context), - textAlign: TextAlign.center, - ), - icon: Icon( - e.icon(PhosphorIconsStyle.light)), - onTap: () => addTool(ShapeTool( - property: ShapeProperty(shape: e))), - )), - ...textures.map((e) => BoxTile( - title: Text( - e.getLocalizedName(context), - textAlign: TextAlign.center, - ), - icon: Icon( - e.icon(PhosphorIconsStyle.light)), - onTap: () => - addTool(TextureTool(texture: e)), - )), - ], - ), - const SizedBox(height: 16), - ], - if (actions.isNotEmpty) ...[ - _ToolsListView( - isMobile: isMobile, - title: AppLocalizations.of(context).actions, - children: actions.map(buildTool).toList(), - ), - const SizedBox(height: 16), + const SizedBox(height: 16), + ], + if (tools.isEmpty && + shapes.isEmpty && + textures.isEmpty && + actions.isEmpty) + Padding( + padding: const EdgeInsets.symmetric( + vertical: 64, horizontal: 16), + child: Text( + AppLocalizations.of(context).noElements, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + if (tools.isNotEmpty) ...[ + _ToolsListView( + isMobile: isMobile, + title: AppLocalizations.of(context).tools, + children: tools.map(buildTool).toList(), + ), + const SizedBox(height: 16), + ], + if (shapes.isNotEmpty || textures.isNotEmpty) ...[ + _ToolsListView( + isMobile: isMobile, + title: AppLocalizations.of(context).surface, + children: [ + ...shapes.map((e) => BoxTile( + title: Text( + e.getLocalizedName(context), + textAlign: TextAlign.center, + ), + icon: Icon( + e.icon(PhosphorIconsStyle.light)), + onTap: () => addTool(ShapeTool( + property: ShapeProperty(shape: e))), + )), + ...textures.map((e) => BoxTile( + title: Text( + e.getLocalizedName(context), + textAlign: TextAlign.center, + ), + icon: Icon( + e.icon(PhosphorIconsStyle.light)), + onTap: () => + addTool(TextureTool(texture: e)), + )), + ], + ), + const SizedBox(height: 16), + ], + if (actions.isNotEmpty) ...[ + _ToolsListView( + isMobile: isMobile, + title: AppLocalizations.of(context).actions, + children: actions.map(buildTool).toList(), + ), + const SizedBox(height: 16), + ], ], - ], - ); - }), + ); + }), + ), ), ), - ), - ]), + ]), + ), ), ); } diff --git a/app/lib/services/sync.dart b/app/lib/services/sync.dart index 7c7f71f5f1f6..0adae2f9b3e3 100644 --- a/app/lib/services/sync.dart +++ b/app/lib/services/sync.dart @@ -105,18 +105,6 @@ class RemoteSync { _filesSubject.onListen = _onListen; } - FileSyncStatus getFileStatus(AssetLocation location) { - final files = this.files; - return files - ?.where((file) => - file.location.remote == location.remote && - location.path.startsWith(file.location.path)) - .fold(FileSyncStatus.offline, (value, element) { - return value.combine(element.status); - }) ?? - FileSyncStatus.offline; - } - RemoteDirectoryFileSystem? buildRemoteSystem() => fileSystem.buildDocumentSystem(remoteStorage).remoteSystem; diff --git a/app/lib/views/property.dart b/app/lib/views/property.dart index ec0a62e305c1..3a14e384a43f 100644 --- a/app/lib/views/property.dart +++ b/app/lib/views/property.dart @@ -32,6 +32,10 @@ class _PropertyViewState extends State begin: Offset.zero, end: const Offset(1.5, 0.0), ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOutCubic)); + late final Animation _fadeAnimation = Tween( + begin: 1.0, + end: 0.0, + ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOutCubic)); final _scrollController = ScrollController(); Selection? _lastSelection; @@ -101,133 +105,140 @@ class _PropertyViewState extends State constraints: BoxConstraints(maxWidth: _size, maxHeight: 500), child: SlideTransition( position: _offsetAnimation, - child: Card( - elevation: 6, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 8), - child: AnimatedSize( - alignment: Alignment.topCenter, - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 200), - child: Row(children: [ - if (!isMobile) - MouseRegion( - cursor: SystemMouseCursors.resizeLeftRight, - child: GestureDetector( - child: const PhosphorIcon( - PhosphorIconsLight.dotsSixVertical), - onPanUpdate: (details) { - final delta = details.delta.dx; - setState(() { - _size -= delta; - _size = max(_size, minSize); - }); - }, + child: FadeTransition( + opacity: _fadeAnimation, + child: Card( + elevation: 6, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 8), + child: AnimatedSize( + alignment: Alignment.topCenter, + curve: Curves.easeInOut, + duration: const Duration(milliseconds: 200), + child: Row(children: [ + if (!isMobile) + MouseRegion( + cursor: SystemMouseCursors.resizeLeftRight, + child: GestureDetector( + child: const PhosphorIcon( + PhosphorIconsLight.dotsSixVertical), + onPanUpdate: (details) { + final delta = details.delta.dx; + setState(() { + _size -= delta; + _size = max(_size, minSize); + }); + }, + ), ), - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Header( - centerTitle: false, - leadingWidth: 60, - title: Text(showing.getLocalizedName(context)), - leading: menuChildren.length <= 1 - ? PhosphorIcon( - icon, - color: Theme.of(context).iconTheme.color, - ) - : MenuAnchor( - controller: controller, - builder: defaultFilledMenuButton( - iconBuilder: - (context, controller, child) => Row( - children: [ - PhosphorIcon( - icon, - color: Theme.of(context) - .colorScheme - .onPrimary, - ), - const SizedBox(width: 8), - PhosphorIcon( - controller.isOpen - ? PhosphorIconsLight.caretUp - : PhosphorIconsLight - .caretDown, - color: Theme.of(context) - .colorScheme - .onPrimary, - size: 12, - ), - ], + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Header( + centerTitle: false, + leadingWidth: 60, + title: Text(showing.getLocalizedName(context)), + leading: menuChildren.length <= 1 + ? PhosphorIcon( + icon, + color: + Theme.of(context).iconTheme.color, + ) + : MenuAnchor( + controller: controller, + builder: defaultFilledMenuButton( + iconBuilder: + (context, controller, child) => + Row( + children: [ + PhosphorIcon( + icon, + color: Theme.of(context) + .colorScheme + .onPrimary, + ), + const SizedBox(width: 8), + PhosphorIcon( + controller.isOpen + ? PhosphorIconsLight.caretUp + : PhosphorIconsLight + .caretDown, + color: Theme.of(context) + .colorScheme + .onPrimary, + size: 12, + ), + ], + ), + tooltip: + AppLocalizations.of(context).icon, ), - tooltip: - AppLocalizations.of(context).icon, + menuChildren: menuChildren, ), - menuChildren: menuChildren, - ), - actions: [ - if (showing.showDeleteButton) - IconButton( - icon: const PhosphorIcon( - PhosphorIconsLight.trash), + actions: [ + if (showing.showDeleteButton) + IconButton( + icon: const PhosphorIcon( + PhosphorIconsLight.trash), + tooltip: + AppLocalizations.of(context).delete, + onPressed: () { + selection?.onDelete(context); + context + .read() + .resetSelection(force: true); + }), + if (help.isNotEmpty) + IconButton( tooltip: - AppLocalizations.of(context).delete, - onPressed: () { - selection?.onDelete(context); - context - .read() - .resetSelection(force: true); - }), - if (help.isNotEmpty) - IconButton( - tooltip: AppLocalizations.of(context).help, + AppLocalizations.of(context).help, + icon: const PhosphorIcon( + PhosphorIconsLight.sealQuestion), + onPressed: () => openHelp(help), + ), + const SizedBox( + height: 16, child: VerticalDivider()), + if (!isMobile) + IconButton( + tooltip: state.pinned + ? AppLocalizations.of(context).unpin + : AppLocalizations.of(context).pin, + icon: state.pinned + ? const PhosphorIcon( + PhosphorIconsFill.pushPin) + : const PhosphorIcon( + PhosphorIconsLight.pushPin), + onPressed: () => context + .read() + .togglePin(), + ), + const SizedBox(width: 8), + IconButton.outlined( + tooltip: AppLocalizations.of(context).close, icon: const PhosphorIcon( - PhosphorIconsLight.sealQuestion), - onPressed: () => openHelp(help), - ), - const SizedBox( - height: 16, child: VerticalDivider()), - if (!isMobile) - IconButton( - tooltip: state.pinned - ? AppLocalizations.of(context).unpin - : AppLocalizations.of(context).pin, - icon: state.pinned - ? const PhosphorIcon( - PhosphorIconsFill.pushPin) - : const PhosphorIcon( - PhosphorIconsLight.pushPin), - onPressed: () => context - .read() - .togglePin(), + PhosphorIconsLight.x), + onPressed: _closeView, ), - const SizedBox(width: 8), - IconButton.outlined( - tooltip: AppLocalizations.of(context).close, - icon: - const PhosphorIcon(PhosphorIconsLight.x), - onPressed: _closeView, + ], + ), + Flexible( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 16), + child: ListView( + shrinkWrap: true, + primary: true, + children: + showing.buildProperties(context)), ), - ], - ), - Flexible( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 16), - child: ListView( - shrinkWrap: true, - primary: true, - children: showing.buildProperties(context)), ), - ), - ], - )), - ]), + ], + )), + ]), + ), ), ), ), diff --git a/metadata/en-US/changelogs/120.txt b/metadata/en-US/changelogs/120.txt index bb3cc19e7233..5969e16dfaa2 100644 --- a/metadata/en-US/changelogs/120.txt +++ b/metadata/en-US/changelogs/120.txt @@ -1,5 +1,7 @@ * Add layer merging * Add option to open context menus with right click on desktop or long press on mobile +* Add safe area to add dialog +* Add fade transition for property view * Remove asking for name on layer creation * Fix layer rendering * Fix pin icon in property view