gumbarros / DevWidgets

DevWidgets is a Flutter application with several tools such as generators, formatters and converters for developers. It's directly inspired by DevToys.
https://gumbarros.github.io/DevWidgets
MIT License
153 stars 13 forks source link

Implement Lipsum & UUID #8

Closed dominic-schmid closed 1 year ago

dominic-schmid commented 1 year ago

Hi there!

The original DevToys is a godsend to me, so I'm glad I can contribute to it in some form or another! This is my first time really working on an open source project, so there may be things I'm unaware of, please don't hesitate to mention them.

Anyways.

With this PR I have implemented the GeneratorGroup with two new Tools. Although I've never used Getx in a Flutter project before, I've tried to follow the structure and modularity of the repo as well as I could.

At first, I wanted to split this into two separate PRs but since the tools depend on the generators group to be implemented, I decided to simply commit them separately and combine them into the same PR.

Lorem Ipsum

This generator uses the ipsum package I wrote based on the lipsum library for Python.

It lets you generate a specified amount of

with some other options.

image

Note: I left a TODO for the best implementation of the LipsumGeneratorController lib/presentation/generators/controllers/lipsum_generator_controller.dart

Since a change to a configuration setting should instantly regenrate the output text, I added listeners to all the actionWidgets. I'm not sure if I can reference the controller Rx<T> fields when calling the regenerate function inside the listener or if its callback value needs to be used for an accurate value (similar to React's useState hook).

To be safe, I used the callback and added parameters in the generator function. The TODO is simply there so it can be cleaned up on the next commit.

UUID

This generator uses the popular UUID package to generate a specified amount of V1 or V4 UUIDs.

You can enable hyphens and uppercase, just like in the original DevToys.

image

Output Toolbar

I added a new, optional parameter List<Widget> actionButtons to the OutputToolbar widget. It gets passed down through the OutputEditor widget.

In the original DevToys you generate UUIDs by clicking a button and append them to the output, but there must be a way to clear it again. For future-proof-ness, I added a whole list instead of only the clear button.

I followed the style guide for Clear buttons from other IO widgets in the repo.

OutputEditor(
    outputController: controller.outputController,
    actionButtons: [
        ElevatedButton.icon(
            icon: FaIcon(FontAwesomeIcons.xmark),
            label: Text("clear".tr),
            onPressed: () => controller.outputController.clear(),
        ),
    ],
)

Other

gumbarros commented 1 year ago

Hello @dominic-schmid ! Thanks for the contribution! Congratulation on the tools and code quality, amazing job!

dominic-schmid commented 1 year ago

Awesome, @gumbarros thanks for merging. Could you maybe tell me what the preferred way of handling listener events is so I know for other tools in the future?

gumbarros commented 1 year ago

Awesome, @gumbarros thanks for merging. Could you maybe tell me what the preferred way of handling listener events is so I know for other tools in the future?

@dominic-schmid I think the way you handled was great, but the official way is better, you can use:

  ever(counter, (value) => print("$value has been changed!!!"));

I refactored to use ever and everything is working as expected :

class LipsumGeneratorController extends GetxController {
  final LipsumGeneratorTool tool;
  late CodeController outputController;

  Rx<LipsumType?> lipsumType = LipsumType.words.obs;
  Rx<bool> startWithLorem = true.obs;
  Rx<int> count = 5.obs;

  LipsumGeneratorController(this.tool);

  void _regenerateLipsum() {
    String generatedText = tool.generator.generate(
      type: lipsumType.value ?? LipsumType.words,
      count: count.value,
      startWithLorem: startWithLorem.value,
    );

    try {
      outputController.text = generatedText;
    } catch (_) {
      //Bug on code_text_field package.
    }
  }

  @override
  void onInit() {
    outputController = CodeControllerFactory.getInstance(language: json);

    ever(count, (_) => _regenerateLipsum());
    ever(lipsumType, (_) => _regenerateLipsum());
    ever(startWithLorem, (_) => _regenerateLipsum());

    /// Generate initial text
    _regenerateLipsum();

    super.onInit();
  }
}
gumbarros commented 1 year ago

You could also use a normal controller to outputController instead of a CodeController. The CodeController is used only for VSCode-like text boxes.

late TextEditingController outputController;
//...
outputController = TextEditingController()