-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds support to update collection details - closes #216
- Loading branch information
Showing
14 changed files
with
419 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 121 additions & 2 deletions
123
lib/application/pages/home/collections/update/update_collection_details.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,127 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/services.dart'; | ||
import 'package:flutter_hooks/flutter_hooks.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:layoutr/common_layout.dart'; | ||
import 'package:memo/application/constants/exception_strings.dart'; | ||
import 'package:memo/application/constants/strings.dart' as strings; | ||
import 'package:memo/application/hooks/rich_text_field_controller_hook.dart'; | ||
import 'package:memo/application/hooks/tags_controller_hook.dart'; | ||
import 'package:memo/application/theme/theme_controller.dart'; | ||
import 'package:memo/application/view-models/home/update_collection_details_vm.dart'; | ||
import 'package:memo/application/widgets/theme/custom_text_field.dart'; | ||
import 'package:memo/application/widgets/theme/rich_text_field.dart'; | ||
import 'package:memo/application/widgets/theme/tags_field.dart'; | ||
import 'package:memo/application/widgets/unfocus_detector.dart'; | ||
import 'package:memo/domain/validators/collection_validators.dart' as validators; | ||
|
||
class UpdateCollectionDetails extends StatelessWidget { | ||
class UpdateCollectionDetails extends HookWidget { | ||
@override | ||
Widget build(BuildContext context) { | ||
return Container(color: Colors.red, child: Center(child: Text('Detalhes'))); | ||
return UnfocusDetector( | ||
child: SingleChildScrollView( | ||
child: Column( | ||
children: [ | ||
_NameField(), | ||
context.verticalBox(Spacing.large), | ||
_TagsField(), | ||
context.verticalBox(Spacing.large), | ||
_DescriptionField(), | ||
], | ||
).withSymmetricalPadding(context, vertical: Spacing.large, horizontal: Spacing.small), | ||
), | ||
); | ||
} | ||
} | ||
|
||
class _NameField extends HookConsumerWidget { | ||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final vm = ref.read(updateCollectionDetailsVM.notifier); | ||
final state = ref.watch(updateCollectionDetailsVM); | ||
|
||
final controller = useTextEditingController(text: state.metadata.name); | ||
final focus = useFocusNode(); | ||
|
||
useEffect(() { | ||
void onNameUpdate() => vm.updateName(controller.text); | ||
|
||
controller.addListener(onNameUpdate); | ||
return () => controller.removeListener(onNameUpdate); | ||
}); | ||
|
||
final nameLength = state.metadata.name.length; | ||
return CustomTextField( | ||
controller: controller, | ||
focusNode: focus, | ||
labelText: strings.collectionName, | ||
inputFormatters: [ | ||
LengthLimitingTextInputFormatter(validators.collectionNameMaxLength), | ||
], | ||
helperText: '$nameLength/${validators.collectionNameMaxLength} caracteres', | ||
errorText: state is UpdateDetailsInvalid && state.nameException != null && !focus.hasFocus | ||
? descriptionForException(state.nameException!) | ||
: null, | ||
); | ||
} | ||
} | ||
|
||
class _TagsField extends HookConsumerWidget { | ||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final vm = ref.read(updateCollectionDetailsVM.notifier); | ||
|
||
final controller = useTagsController(); | ||
|
||
useEffect(() { | ||
void onTagsUpdate() => vm.updateTags(controller.tags); | ||
|
||
controller.addListener(onTagsUpdate); | ||
return () => controller.removeListener(onTagsUpdate); | ||
}); | ||
|
||
return const TagsField(); | ||
} | ||
} | ||
|
||
class _DescriptionField extends HookConsumerWidget { | ||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final theme = useTheme(ref); | ||
final textTheme = Theme.of(context).textTheme; | ||
final vm = ref.read(updateCollectionDetailsVM.notifier); | ||
final state = ref.watch(updateCollectionDetailsVM); | ||
|
||
final controller = useRichTextEditingController(richText: state.metadata.description.richText); | ||
final focus = useFocusNode(); | ||
final hasFocus = useState(focus.hasFocus); | ||
|
||
useEffect(() { | ||
void onDescriptionUpdate() => vm.updateDescription(controller.value); | ||
void onFocusUpdate() => hasFocus.value = focus.hasFocus; | ||
|
||
controller.addListener(onDescriptionUpdate); | ||
focus.addListener(onFocusUpdate); | ||
|
||
return () { | ||
controller.removeListener(onDescriptionUpdate); | ||
focus.removeListener(onFocusUpdate); | ||
}; | ||
}); | ||
|
||
final descriptionLength = state.metadata.description.plainText.length; | ||
return RichTextField( | ||
controller: controller, | ||
focus: focus, | ||
modalTitle: Text( | ||
strings.detailsDescription, | ||
style: textTheme.bodyText1?.copyWith(color: theme.primarySwatch.shade400), | ||
), | ||
placeholder: strings.collectionDescription, | ||
helperText: '$descriptionLength/${validators.collectionDescriptionMaxLength} caracteres', | ||
errorText: state is UpdateDetailsInvalid && state.descriptionException != null && !focus.hasFocus | ||
? descriptionForException(state.descriptionException!) | ||
: null, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
lib/application/pages/home/collections/update/update_collection_providers.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:memo/application/view-models/home/update_collection_vm.dart'; | ||
|
||
/// Overridable collection id used in the scope of a collection update. | ||
final updateCollectionId = Provider<String?>((_) => throw UnimplementedError(), name: 'updateCollectionId'); | ||
|
||
/// Overridable collection metadata used in the scope of a collection update. | ||
final updateDetailsMetadata = | ||
Provider<CollectionMetadata>((_) => throw UnimplementedError(), name: 'updateDetailsMetadata'); |
18 changes: 0 additions & 18 deletions
18
lib/application/pages/home/collections/update/update_providers.dart
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.