Skip to content

Commit

Permalink
Improve template dialog and default zoom dependent
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Dec 9, 2024
1 parent 780e149 commit 0398a60
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 50 deletions.
1 change: 1 addition & 0 deletions api/lib/src/models/archive.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 16:9
const kThumbnailWidth = 640;
const kThumbnailHeight = 360;
const kThumbnailRatio = 16 / 9;

// Archive specific
const kMetaInfoArchiveDirectory = 'META-INF';
Expand Down
8 changes: 4 additions & 4 deletions api/lib/src/models/tool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ sealed class Tool with _$Tool {
@Default('') String name,
@Default('') String displayIcon,
@Default(LabelMode.text) LabelMode mode,
@Default(true) bool zoomDependent,
@Default(false) bool zoomDependent,
@Default(BasicColors.black) int foreground,
@Default(PackAssetLocation()) PackAssetLocation styleSheet,
@Default(2.0) double scale,
Expand All @@ -86,7 +86,7 @@ sealed class Tool with _$Tool {
factory Tool.pen({
@Default('') String name,
@Default('') String displayIcon,
@Default(true) bool zoomDependent,
@Default(false) bool zoomDependent,
@Default(0.5) double shapeDetectionTime,
@Default(false) bool shapeDetectionEnabled,
@Default(PenProperty()) PenProperty property,
Expand Down Expand Up @@ -135,7 +135,7 @@ sealed class Tool with _$Tool {
factory Tool.shape({
@Default('') String name,
@Default('') String displayIcon,
@Default(true) bool zoomDependent,
@Default(false) bool zoomDependent,
@Default(0) double constrainedWidth,
@Default(0) double constrainedHeight,
@Default(0) double constrainedAspectRatio,
Expand Down Expand Up @@ -181,7 +181,7 @@ sealed class Tool with _$Tool {
factory Tool.texture({
@Default('') String name,
@Default('') String displayIcon,
@Default(true) bool zoomDependent,
@Default(false) bool zoomDependent,
@Default(0) double constrainedWidth,
@Default(0) double constrainedHeight,
@Default(0) double constrainedAspectRatio,
Expand Down
8 changes: 4 additions & 4 deletions api/lib/src/models/tool.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ class _$LabelToolImpl extends LabelTool {
{this.name = '',
this.displayIcon = '',
this.mode = LabelMode.text,
this.zoomDependent = true,
this.zoomDependent = false,
this.foreground = BasicColors.black,
this.styleSheet = const PackAssetLocation(),
this.scale = 2.0,
Expand Down Expand Up @@ -929,7 +929,7 @@ class _$PenToolImpl extends PenTool {
_$PenToolImpl(
{this.name = '',
this.displayIcon = '',
this.zoomDependent = true,
this.zoomDependent = false,
this.shapeDetectionTime = 0.5,
this.shapeDetectionEnabled = false,
this.property = const PenProperty(),
Expand Down Expand Up @@ -1805,7 +1805,7 @@ class _$ShapeToolImpl extends ShapeTool {
_$ShapeToolImpl(
{this.name = '',
this.displayIcon = '',
this.zoomDependent = true,
this.zoomDependent = false,
this.constrainedWidth = 0,
this.constrainedHeight = 0,
this.constrainedAspectRatio = 0,
Expand Down Expand Up @@ -2691,7 +2691,7 @@ class _$TextureToolImpl extends TextureTool {
_$TextureToolImpl(
{this.name = '',
this.displayIcon = '',
this.zoomDependent = true,
this.zoomDependent = false,
this.constrainedWidth = 0,
this.constrainedHeight = 0,
this.constrainedAspectRatio = 0,
Expand Down
8 changes: 4 additions & 4 deletions api/lib/src/models/tool.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

158 changes: 121 additions & 37 deletions app/lib/dialogs/template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import 'package:butterfly/actions/new.dart';
import 'package:butterfly/api/file_system.dart';
import 'package:butterfly/api/save.dart';
import 'package:butterfly/cubits/settings.dart';
import 'package:butterfly/dialogs/name.dart';
import 'package:butterfly/visualizer/tool.dart';
import 'package:butterfly/widgets/connection_button.dart';
import 'package:butterfly/widgets/option_button.dart';
import 'package:butterfly_api/butterfly_api.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand All @@ -16,6 +18,19 @@ import '../bloc/document_bloc.dart';
import '../widgets/editable_list_tile.dart';
import 'delete.dart';

Future<void> _overrideTools(TemplateFileSystem templateSystem,
DocumentBloc bloc, List<NoteData> templates) async {
final state = bloc.state;
if (state is! DocumentLoaded) return;
final tools = state.info.tools;
for (var template in templates) {
final info = template.getInfo();
if (info == null) continue;
template = template.setInfo(info.copyWith(tools: tools));
await templateSystem.updateFile(template.name ?? '', template);
}
}

class TemplateDialog extends StatefulWidget {
final DocumentBloc? bloc;
const TemplateDialog({super.key, this.bloc});
Expand Down Expand Up @@ -137,7 +152,7 @@ class _TemplateDialogState extends State<TemplateDialog> {
IconButton(
onPressed: () => _showCreateDialog(widget.bloc!),
tooltip: AppLocalizations.of(context).create,
icon: const PhosphorIcon(PhosphorIconsLight.plus),
icon: const PhosphorIcon(PhosphorIconsLight.floppyDisk),
)
],
],
Expand Down Expand Up @@ -171,7 +186,7 @@ class _TemplateDialogState extends State<TemplateDialog> {
return _TemplateItem(
template: template,
fileSystem: _templateSystem,
replace: widget.bloc != null,
bloc: widget.bloc,
selected: _selectedTemplates.contains(template.name),
onSelected: () {
setState(() {
Expand Down Expand Up @@ -232,25 +247,15 @@ class _TemplateDialogState extends State<TemplateDialog> {
IconButton(
icon: const PhosphorIcon(PhosphorIconsLight.wrench),
tooltip: AppLocalizations.of(context).overrideTools,
onPressed: () async {
final state = widget.bloc!.state;
if (state is! DocumentLoaded) return;
final tools = state.info.tools;
for (final name in _selectedTemplates) {
var template = templates.firstWhereOrNull(
(element) => element.name == name);
if (template == null) continue;
final info = template.getInfo();
if (info == null) continue;
template = template
.setInfo(info.copyWith(tools: tools));
await _templateSystem.updateFile(
name, template);
}
setState(() {
_selectedTemplates.clear();
});
},
onPressed: () => _overrideTools(
_templateSystem,
widget.bloc!,
templates
.where((element) => _selectedTemplates
.contains(element.name))
.toList())
.then((value) =>
setState(() => _selectedTemplates.clear())),
),
IconButton(
icon: const PhosphorIcon(PhosphorIconsLight.trash),
Expand Down Expand Up @@ -344,15 +349,16 @@ class _TemplateDialogState extends State<TemplateDialog> {
class _TemplateItem extends StatelessWidget {
final NoteData template;
final TemplateFileSystem fileSystem;
final DocumentBloc? bloc;
final VoidCallback onChanged, onSelected, onUnselected;
final bool replace, selected;
final bool selected;

const _TemplateItem({
required this.template,
required this.fileSystem,
required this.onChanged,
required this.replace,
required this.selected,
this.bloc,
required this.onSelected,
required this.onUnselected,
});
Expand All @@ -363,21 +369,36 @@ class _TemplateItem extends StatelessWidget {
final settings = settingsCubit.state;
final isDefault = settings.defaultTemplate == template.name;
final metadata = template.getMetadata();
final info = template.getInfo();
if (metadata == null) {
return const SizedBox();
}
final thumbnail = template.getThumbnail();
const leading = PhosphorIcon(
const fallback = PhosphorIcon(
PhosphorIconsLight.file,
size: 48,
);
final leading = thumbnail != null
? AspectRatio(
aspectRatio: kThumbnailRatio,
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.memory(
thumbnail,
fit: BoxFit.cover,
cacheHeight: kThumbnailWidth,
cacheWidth: kThumbnailHeight,
)),
)
: fallback;
return EditableListTile(
initialValue: metadata.name,
subtitle: Text(metadata.description),
leading: SizedBox(
height: 64,
width: 96,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Checkbox(
value: selected,
Expand All @@ -390,17 +411,7 @@ class _TemplateItem extends StatelessWidget {
},
),
const SizedBox(width: 8),
Expanded(
child: thumbnail != null
? Image.memory(
thumbnail,
fit: BoxFit.contain,
cacheWidth: 64,
cacheHeight: 64,
errorBuilder: (context, error, stackTrace) => leading,
)
: leading,
),
Flexible(child: leading),
],
),
),
Expand All @@ -421,6 +432,79 @@ class _TemplateItem extends StatelessWidget {
onChanged();
},
),
if (bloc != null)
MenuItemButton(
leadingIcon: const PhosphorIcon(PhosphorIconsLight.trash),
child: Text(AppLocalizations.of(context).delete),
onPressed: () async {
_overrideTools(fileSystem, bloc!, [template]);
},
),
MenuItemButton(
leadingIcon: const PhosphorIcon(PhosphorIconsLight.copy),
child: Text(AppLocalizations.of(context).duplicate),
onPressed: () async {
final result = await showDialog<String>(
context: context, builder: (ctx) => NameDialog(
value: template.name,
));
if (result == null) return;
if (context.mounted) {
await fileSystem.createFileWithName(template.setMetadata(metadata.copyWith(name: result)), name: result);
onChanged();
}
},
),
MenuItemButton(
leadingIcon: const PhosphorIcon(PhosphorIconsLight.info),
child: Text(AppLocalizations.of(context).information),
onPressed: () async {
showLeapBottomSheet(
context: context,
titleBuilder: (context) => Text(metadata.name),
leadingBuilder: (context) => Center(child: leading),
leadingWidth: 128,
childrenBuilder: (context) => [
Padding(
padding: const EdgeInsets.all(8.0),
child: Card.filled(
child: Padding(
padding: EdgeInsets.all(2),
child: Column(children: [
if (metadata.description.isNotEmpty)
ListTile(
title: Text(AppLocalizations.of(context).description),
subtitle: Text(metadata.description),
),
if (metadata.directory.isNotEmpty)
ListTile(
title: Text(AppLocalizations.of(context).directory),
subtitle: Text(metadata.directory),
),
ListTile(
title: Text(AppLocalizations.of(context).tools),
subtitle: Wrap(
alignment: WrapAlignment.center,
children: [
for (final tool in info?.tools ?? <Tool>[])
SizedBox.square(
dimension: 64,
child: OptionButton(
icon:
Icon(tool.icon(PhosphorIconsStyle.light)),
tooltip: tool.name,
),
),
],
),
),
]),
)),
)
],
);
},
),
MenuItemButton(
leadingIcon: const PhosphorIcon(PhosphorIconsLight.trash),
child: Text(AppLocalizations.of(context).delete),
Expand All @@ -436,7 +520,7 @@ class _TemplateItem extends StatelessWidget {
),
],
onTap: () => openNewDocument(
context, replace, template, fileSystem.storage?.identifier),
context, bloc != null, template, fileSystem.storage?.identifier),
);
}
}
2 changes: 1 addition & 1 deletion app/lib/views/files/card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AssetCard extends StatelessWidget {
return ConstrainedBox(
constraints: BoxConstraints(maxHeight: height),
child: AspectRatio(
aspectRatio: 16 / 9,
aspectRatio: kThumbnailRatio,
child: Card(
elevation: 5,
clipBehavior: Clip.hardEdge,
Expand Down
7 changes: 7 additions & 0 deletions metadata/en-US/changelogs/124.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
* Improve template dialog
* Add override tools in context menu
* Add information button
* Add duplicate button
* Change create template button to save icon
* Improve thumbnail display to have rounded corners
* Change zoom dependent to false by default
* Fix zoom dependent not working correctly with the label tool ([#765](https://github.com/LinwoodDev/Butterfly/issues/765))

Read more here: https://linwood.dev/butterfly/2.2.3-rc.1

0 comments on commit 0398a60

Please sign in to comment.