From fda18f96526dfee0cb95809a897920fa6e83d31f Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Mon, 3 Oct 2022 11:36:27 +0100 Subject: [PATCH] Added more help classes, moved files to public --- CHANGELOG.md | 4 + README.md | 2 +- lib/flutter_dev_utils.dart | 3 - .../classes/help_abstract_class.dart | 84 +++++++++++ lib/inline_help/classes/help_annotations.dart | 0 lib/inline_help/classes/help_interface.dart | 2 + .../classes}/help_singleton.dart | 0 lib/inline_help/dart/help_dart.dart | 5 + lib/inline_help/dart/help_dart_syntax.dart | 58 ++++++++ lib/inline_help/dart/help_inheritance.dart | 15 ++ .../dart/help_initialiser_list.dart | 14 ++ lib/inline_help/dart/help_modifiers.dart | 20 +++ lib/inline_help/dart/help_sizing.dart | 63 ++++++++ .../debugging}/help_error.dart | 5 + .../debugging/help_exceptions.dart | 5 + lib/inline_help/flutter/help_animations.dart | 137 ++++++++++++++++++ lib/inline_help/flutter/help_async.dart | 28 ++++ lib/inline_help/flutter/help_firebase.dart | 13 ++ lib/inline_help/flutter/help_flutter.dart | 110 ++++++++++++++ .../flutter/help_launcher_icons.dart | 34 +++++ lib/inline_help/flutter/help_ui_approach.dart | 30 ++++ .../help_change_notifier.dart | 15 ++ .../state_management/help_focus.dart | 38 +++++ .../state_management/help_provider.dart | 97 +++++++++++++ .../help_state_management.dart | 53 +++++++ pubspec.yaml | 4 +- 26 files changed, 833 insertions(+), 6 deletions(-) create mode 100644 lib/inline_help/classes/help_abstract_class.dart create mode 100644 lib/inline_help/classes/help_annotations.dart create mode 100644 lib/inline_help/classes/help_interface.dart rename lib/{src/inline_help => inline_help/classes}/help_singleton.dart (100%) create mode 100644 lib/inline_help/dart/help_dart.dart create mode 100644 lib/inline_help/dart/help_dart_syntax.dart create mode 100644 lib/inline_help/dart/help_inheritance.dart create mode 100644 lib/inline_help/dart/help_initialiser_list.dart create mode 100644 lib/inline_help/dart/help_modifiers.dart create mode 100644 lib/inline_help/dart/help_sizing.dart rename lib/{src/inline_help => inline_help/debugging}/help_error.dart (50%) create mode 100644 lib/inline_help/debugging/help_exceptions.dart create mode 100644 lib/inline_help/flutter/help_animations.dart create mode 100644 lib/inline_help/flutter/help_async.dart create mode 100644 lib/inline_help/flutter/help_firebase.dart create mode 100644 lib/inline_help/flutter/help_flutter.dart create mode 100644 lib/inline_help/flutter/help_launcher_icons.dart create mode 100644 lib/inline_help/flutter/help_ui_approach.dart create mode 100644 lib/inline_help/state_management/help_change_notifier.dart create mode 100644 lib/inline_help/state_management/help_focus.dart create mode 100644 lib/inline_help/state_management/help_provider.dart create mode 100644 lib/inline_help/state_management/help_state_management.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index c20c022..43024d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.1+2 + +* Added a lot more help classes + ## 0.0.1+1 * Exposed Help classes diff --git a/README.md b/README.md index 70a22c1..4f12425 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Flutter dev utils to make your life easier * CallerLogger * Built off logger package with functionality to print caller, ignore certain callers, and filter printed logs by caller type * Help - * HelpFoo classes which can be used for inline code help. + * Stop clicking those purple stackoverflow links! HelpFoo classes can be used for inline code help. ![Alt Text](https://github.com/Kek-Tech/flutter_dev_utils/blob/main/assets/HelpClass.gif) diff --git a/lib/flutter_dev_utils.dart b/lib/flutter_dev_utils.dart index 5e6df3c..b8f8b27 100644 --- a/lib/flutter_dev_utils.dart +++ b/lib/flutter_dev_utils.dart @@ -1,8 +1,5 @@ library flutter_dev_utils; -export 'package:flutter_dev_utils/src/inline_help/help_error.dart'; -export 'package:flutter_dev_utils/src/inline_help/help_singleton.dart'; - export 'package:flutter_dev_utils/src/try_handler/sync_try_handler.dart'; export 'package:flutter_dev_utils/src/try_handler/async_try_handler.dart'; export 'package:flutter_dev_utils/src/caller_logger/caller_logger.dart'; diff --git a/lib/inline_help/classes/help_abstract_class.dart b/lib/inline_help/classes/help_abstract_class.dart new file mode 100644 index 0000000..e60f6f5 --- /dev/null +++ b/lib/inline_help/classes/help_abstract_class.dart @@ -0,0 +1,84 @@ +/// TODO +/// # Help with Abstract classes +/// +/// * Abstract classes cannot be instantiated. +/// +/// ## Use cases +/// +/// ### Extending an abstract class to override its function +/// ``` +/// abstract class AbstractClass { +/// void function(); +/// } +/// +/// class Example extends AbstractClass { +/// @override +/// void function() => print('hi'); +/// } +/// ``` +/// +/// ### Extending an abstract class to inherit its instance variable +/// +/// * Instance variable has to be declared on instantiation of subclass. +/// +/// ``` +/// abstract class AbstractClass { +/// final String instanceVar; +/// AbstractClass(this.instanceVar); +/// } +/// +/// class Example extends AbstractClass { +/// Example(super.instanceVar); +/// } +/// ``` +/// +/// ### Implementing an abstract class to override its instance variable +/// ``` +/// abstract class AbstractClass { +/// final String instanceVar; +/// AbstractClass(this.instanceVar); +/// } +/// +/// class Example implements AbstractClass { +/// @override +/// final String instanceVar = 'const'; +/// Example(); +/// } +/// ``` +/// ### Mixing in an abstract class to inherit its instance variable +/// +/// * Declaration of instance variable not necessary on instantiation of subclass +/// +/// ``` +/// abstract class AbstractClass { +/// String? instanceVar; +/// } +/// +/// class Example with AbstractClass { +/// Example(); +/// } +/// ``` +/// +/// ### Implementing an abstract class to inherit its members (interface) +/// +/// * An interface is a superclass that acts as a blueprint for a subclass +/// * Implementing an abstract class forces the subclass to override all members of the super +/// * See HelpInterface for more details on `implements` +/// +/// ``` +/// abstract class AbstractClass { +/// String? instanceVariable; +/// +/// void _function(); +/// } +/// +/// class Example implements AbstractClass { +/// @override +/// void _function() => null; +/// +/// @override +/// String? instanceVariable = ''; +/// } +/// ``` + +abstract class HelpAbstractClass {} diff --git a/lib/inline_help/classes/help_annotations.dart b/lib/inline_help/classes/help_annotations.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/inline_help/classes/help_interface.dart b/lib/inline_help/classes/help_interface.dart new file mode 100644 index 0000000..306f945 --- /dev/null +++ b/lib/inline_help/classes/help_interface.dart @@ -0,0 +1,2 @@ +/// TODO +abstract class HelpInterface {} diff --git a/lib/src/inline_help/help_singleton.dart b/lib/inline_help/classes/help_singleton.dart similarity index 100% rename from lib/src/inline_help/help_singleton.dart rename to lib/inline_help/classes/help_singleton.dart diff --git a/lib/inline_help/dart/help_dart.dart b/lib/inline_help/dart/help_dart.dart new file mode 100644 index 0000000..edc651b --- /dev/null +++ b/lib/inline_help/dart/help_dart.dart @@ -0,0 +1,5 @@ +/// Help with important concepts in Dart +/// +/// + +class HelpDart {} diff --git a/lib/inline_help/dart/help_dart_syntax.dart b/lib/inline_help/dart/help_dart_syntax.dart new file mode 100644 index 0000000..1026b2d --- /dev/null +++ b/lib/inline_help/dart/help_dart_syntax.dart @@ -0,0 +1,58 @@ +/// # Help with Dart syntax +/// +/// ## Multiple if +/// ``` +/// (() { +/// /// your code here +/// }()) +/// ``` +/// +/// ## Spread Operator +/// - Can be used to return multiple widgets +/// ``` +/// if (Responsive.isDesktop()) ...[ +/// Text('Desktop') +/// Text('Mode') +/// ] +/// ``` +/// +/// ## Cascade Notation +/// +/// Prevents repeating target for several call methods on same object. +/// +/// ``` +/// List list = []; +/// list.add(color1); +/// list.add(color2); +/// +/// list +/// ..add(color1) +/// ..add(color2); +/// ``` +/// +/// ## Arrow +/// ``` +/// => expression, +/// /// is equivalent to +/// {return expression;}, +/// ``` +/// +/// ## Closure/Inline Functions +/// ``` +/// () => expression +/// +/// /// is equivalent to +/// function () { +/// return expression +/// } +/// ``` +/// +/// ## Anonymous Multiline Function +/// ``` +/// () {expression} +/// /// is equivalent to +/// function () { +/// return expression +/// } +/// ``` +class HelpDartSyntax {} diff --git a/lib/inline_help/dart/help_inheritance.dart b/lib/inline_help/dart/help_inheritance.dart new file mode 100644 index 0000000..aee5178 --- /dev/null +++ b/lib/inline_help/dart/help_inheritance.dart @@ -0,0 +1,15 @@ +/// # Inheritance +/// +/// ## extends +/// +/// - making all properties, variables, functions of superclass available to subclass +/// +/// ## implements +/// +/// - making type of superclass available to subclass +/// - all functions must be implemented/overridden +/// +/// ## with (mixin) +/// +/// - making properties, variables, functions of a different class available to a subclass +class HelpInheritance {} diff --git a/lib/inline_help/dart/help_initialiser_list.dart b/lib/inline_help/dart/help_initialiser_list.dart new file mode 100644 index 0000000..2986c9e --- /dev/null +++ b/lib/inline_help/dart/help_initialiser_list.dart @@ -0,0 +1,14 @@ +/// # Initialiser List (:) +/// +/// Used to: +/// - Initialise list of expressions that can: +/// - access constructor parameters +/// - assign to instance fields (even final instance fields!) +/// - Call other constructors +/// - e.g., superclass +/// - Assert constructor parameters +/// +/// NOTE: +/// - Initialiser list is executed before constructor body +/// - Use `this.instanceVariable` when there is a name conflict, else omit +class HelpInitialiserList {} diff --git a/lib/inline_help/dart/help_modifiers.dart b/lib/inline_help/dart/help_modifiers.dart new file mode 100644 index 0000000..82f8c4e --- /dev/null +++ b/lib/inline_help/dart/help_modifiers.dart @@ -0,0 +1,20 @@ +/// # Modifiers +/// +/// ## static +/// +/// - modifies members of a class (variables, functions) +/// - only affects the class, not on instances of the class +/// +/// ## final +/// +/// - modifies variables (`var, int, double`) +/// - must be assigned on init +/// - shallow immutability: e.g., final collection members can be mutable, collection itself is immutable +/// +/// ## const +/// +/// - modifies values and objects (`[1,2,3], Point(2,3)`) +/// - compile time constant: state can be determined at compile time and is then frozen (e.g., `1+2` is compile time const, `DateTime.now()` is not) +/// - deep (transitive) immutability: e.g., const collection members are immutable, recursively +/// - canonicalised values and objects: all assignments of the const value/object will refer to the same instance +class HelpModifiers {} diff --git a/lib/inline_help/dart/help_sizing.dart b/lib/inline_help/dart/help_sizing.dart new file mode 100644 index 0000000..35d4a8d --- /dev/null +++ b/lib/inline_help/dart/help_sizing.dart @@ -0,0 +1,63 @@ +/// # Sizing +/// ## Sizes, Constraints and Positions +/// ### Rules +/// - Constraints go down +/// - Sizes go up +/// - Parent sets position +/// ### Process +/// For an arbitrary widget X, its parent Y, and its children Z +/// 1. Y passes its constraints down to X +/// - min/max height/width +/// 2. X passes its constraints down to Z +/// 3. X asks Z what size they are +/// - width/height +/// 4. X sets positions of Z +/// 5. X tells Y its final size +/// +/// ### Limitations +/// - Size defined in widget only within constraints of parent +/// - Widget does not know/decide its position +/// - Defining alignment must be specific or child size may be ignored +/// +/// ### Mechanisms +/// - RenderBox +/// - Underlying object used to render widgets +/// +/// ### Types of Constraints +/// #### As Big As Possible +/// - e.g., +/// - Center +/// - ListView +/// - Container (null width and height) +/// #### Same Size if Possible +/// - e.g., +/// - Transform +/// - Opacity +/// - Container (non null width or height) +/// #### Fixed Size if Possible +/// - e.g., +/// - Image +/// - Text +/// ## BoxConstraints +/// - Passed to Container.constraints +/// - Can specify max/min width/height +/// +/// ## LayoutBuilder +/// - Provides parent constraints to child +/// - Builds at layout time +/// +/// ## FractionallySizedBox +/// - Provides percentage of parent size to child +/// ``` +/// ParentWidget( +/// child: FractionallySizedBox( +/// widthFactor: 0.5, +/// heightFactor: 0.5, +/// child: Container( +/// /// this container won't be larger than +/// /// half of its parent size +/// ), +/// ) +/// ) +/// ``` +class HelpSizing {} diff --git a/lib/src/inline_help/help_error.dart b/lib/inline_help/debugging/help_error.dart similarity index 50% rename from lib/src/inline_help/help_error.dart rename to lib/inline_help/debugging/help_error.dart index 3d363b5..4a08f4b 100644 --- a/lib/src/inline_help/help_error.dart +++ b/lib/inline_help/debugging/help_error.dart @@ -1,3 +1,8 @@ +/// # Errors +/// An Error in Dart should be thrown for unexpected program flow and should not be caught but addressed by the programmer: +/// Error and its subclasses are for programmatic errors. If one of those occurs, your code is bad and you should fix your code. +/// Except in a few special circumstances, idiomatic Dart should throw Errors, but never catch them. They exists specifically to not be caught so that they take down the app and alert the programmer to the location of the bug. +/// /// Flutter Error Types: /// /// * ArgumentError diff --git a/lib/inline_help/debugging/help_exceptions.dart b/lib/inline_help/debugging/help_exceptions.dart new file mode 100644 index 0000000..aaee78f --- /dev/null +++ b/lib/inline_help/debugging/help_exceptions.dart @@ -0,0 +1,5 @@ +/// # Exceptions +/// +/// An Exception in Dart should be thrown for regular, expected program flow and is intended to be caught: +/// An Exception is intended to convey information to the user about a failure, so that the error can be addressed programmatically. It is intended to be caught, and it should contain useful data fields. +class HelpExceptions {} diff --git a/lib/inline_help/flutter/help_animations.dart b/lib/inline_help/flutter/help_animations.dart new file mode 100644 index 0000000..796dab7 --- /dev/null +++ b/lib/inline_help/flutter/help_animations.dart @@ -0,0 +1,137 @@ +/// # Animations +/// +/// Animation Types: +/// +/// ## Drawing-based +/// +/// - Use external framework and export to flutter (e..g, Flare, Lottie) +/// +/// ## Code-based +/// +/// ### Implicit (AnimatedFoo) +/// +/// #### BuiltIn +/// +/// #### Custom: TweenAnimationBuilder +/// +/// ### Explicit (FooTransition) +/// +/// - Requires AnimationController, and managing life cycle inside stateful widget +/// Used if any of the following is true: +/// - Repeats forever +/// - Discontinuous animation +/// - Multiple widgets animating together +/// +/// #### Built In +/// +/// #### Custom +/// +/// ##### AnimatedWidget +/// +/// - Standalone widget +/// - Use Process: +/// 1. Define class to extend `AnimatedWidget` +/// 2. Override `build` to return desired widget which will be animated +/// 3. Add listenable argument to constructor and pass it up to Animated widget as well. This tells the widget what to look out for. +/// 4. Add getter to make listenable argument usable. +/// 5. Add listenable argument to build method to affect widget properties. +/// 6. Create `AnimationController` within `StateWidget` where animation will be used. Ensure `AnimationController` is initialised in `init` and disposed in `dispose`. +/// 7. Extend `StatefulWidget` with `TickerProviderStateMixin` to get a ticker listener. The ticker listens to frameCallback and determines the duration between the current and last frame, and passes it to the controller to control the animation. Implement it in the controller with vsync. +/// 8. Add methods to direct the controller. +/// +/// EXAMPLE: +/// ``` +/// /// 1. +/// class FooTransition extends AnimatedWidget { +/// /// 3. +/// const FooTransition(Type listenableArg) +/// : super(listenable: listenableArg); + +/// /// 4. +/// Animation get listenableArg => listenable + +/// /// 2. +/// @override +/// Widget build(BuildContext context) { +/// /// 5. +/// return ... +/// } + +/// class ExampleStateful extends StatefulWidget { + +/// } + +/// class _ExampleStatefulState extends State +/// with TickerProviderStateMixin { +/// late final AnimationController _controller = AnimationController(vsync: this, ...) +/// ..method1() +/// ..method2(); + +/// @override +/// void dispose() { +/// _controller.dispose(); +/// super.dispose(); +/// } +/// @override +/// Widget build(BuildContext context) { +/// return FooTransition(controller: _controller); +/// } +/// +/// } +/// +/// } +/// +/// ``` +/// ##### CustomPainter +/// +/// - Similar to AnimatedWidget but paints directly to canvas without Widget build paradigm, for complex animations or higher performance. Could cause more performance problems if misused. +/// - CustomPaint is a widget which provides a canvas and takes a CustomPainter to execute paint commands. +/// - Implementation: +/// 1. Define `CustomPaint` widget with painter and child/size in `StateWidget` +/// 2. Define `myPainter` class as extension of `CustomPainter`, override `paint` and `shouldRepaint`. +/// 3. Define paint commands within `paint` function with `canvas.method()`. +/// 4. Define repaint scenarios within `shouldRepaint` if necessary. +/// 5. For animations, pass the controller into the painter and change parameters with progress value. +/// +/// ``` +/// /// 1. +/// class ExampleStateful extends StatefulWidget { +/// +/// } +/// +/// class _ExampleStatefulState extends State +/// with TickerProviderStateMixin { +/// +/// late final AnimationController _controller = AnimationController(vsync: this, ...) +/// ..method1() +/// ..method2(); +/// +/// final customPaint = CustomPaint( +/// painter: MyPainter(_controller), +/// child: myWidget(), +/// ) +/// +/// @override +/// Widget build(BuildContext context) { +/// return customPaint; +/// } +/// +/// class MyPainter extends CustomPainter { +/// @override +/// void paint(ui.Canvas canvas, ui.Size size) { +/// /// paint commands +/// } +/// +/// @override +/// bool shouldRepaint(CustomPainter oldDelegate) { +/// /// hook called when CustomPainter is rebuilt +/// /// when to repaint, set to true if necessary +/// return false; +/// } +/// +/// } +/// ``` +/// ##### AnimatedBuilder +/// - Part of parent widget + +class HelpAnimations {} diff --git a/lib/inline_help/flutter/help_async.dart b/lib/inline_help/flutter/help_async.dart new file mode 100644 index 0000000..d9d3818 --- /dev/null +++ b/lib/inline_help/flutter/help_async.dart @@ -0,0 +1,28 @@ +/// # Asynchronous Programming +/// Completion of other work while waiting for a complex operation to finish. +/// The complex operation is usually set to be the asynchronous function. +/// +/// ## Terminology +/// - Synchronous operation: Blocks other operations from executing till it completes +/// - Synchronous function: Only syncOp +/// - Asynchronous operation: Allows other operations to execute before it completes +/// - Asynchronous function: >=1 asyncOp +/// +/// ## futures +/// - `future`: instance of Future class +/// - Represents result of asyncOp: +/// - Uncompleted, waiting for asyncOp to finish or throw an error +/// - Completed, returns value for successful asyncOp, or throw error +/// - +/// - `Future`: class returning future value of ReturnValueType +/// - +/// +/// ## async +/// ## await +/// +/// # Generators (*) +/// - Function which returns multiple values +/// - e.g., sync function returns `int`, async function returns `Future`, sync generator returns `Iterable`, async generator returns `Stream` +/// - Uses `yield` instead of `return` + +class HelpAsync {} diff --git a/lib/inline_help/flutter/help_firebase.dart b/lib/inline_help/flutter/help_firebase.dart new file mode 100644 index 0000000..535cd44 --- /dev/null +++ b/lib/inline_help/flutter/help_firebase.dart @@ -0,0 +1,13 @@ +/// To host Flutter app on Firebase, +/// +/// 1. Initialise firebase project: `firebase init hosting` +/// 2. Set public directory (build output): `build/web` +/// 3. Single page app for flutter. +/// 4. Generate hosting files with flutter: `flutter build web` +/// 5. Upload hosting files from public directory to firebase: `firebase deploy` +/// 6. Open URL in terminal +/// +/// To use custom domain name, +/// 1. Go to Firebase console > Hosting to get records +/// 2. Go to Google domains and add records +class HelpFirebase {} diff --git a/lib/inline_help/flutter/help_flutter.dart b/lib/inline_help/flutter/help_flutter.dart new file mode 100644 index 0000000..20dc01a --- /dev/null +++ b/lib/inline_help/flutter/help_flutter.dart @@ -0,0 +1,110 @@ +/// # Help with important concepts in Flutter +/// +/// ## Widgets +/// +/// +/// ### StatelessWidget +/// +/// - State in widget immutable once built +/// - Explanation: +/// - Once widget builds element, +/// - Data and functions which exist in widget cannot change what is on the screen +/// - Components: +/// - Widget Tree +/// - Stateless Widget +/// - Builds stateless element and mounts it +/// - Element Tree +/// - Stateless Element +/// - Lifecycle Events +/// - build() called when +/// - Widget created for first time +/// - Parent changes/updates +/// - InheritedWidget changes +/// +/// ### StatefulWidget +/// - State in widget mutable after build +/// - Explanation: +/// - Once widget builds element, +/// - Data and functions which exist in widget can change +/// - Components: +/// - Widget Tree +/// - Stateful Widget +/// 1 Creates stateful element and mounts it +/// 3 Creates state object +/// - State Widget +/// 4 Holds state and used as reference for stateful element +/// 5 Builds stateless element and mounts it +/// 6 Change in state triggers rebuild +/// - Element Tree +/// - Stateful Element +/// 2 Requests state object from stateful widget +/// - Stateless Element +/// - Lifecycle Events +/// - build() called when +/// - Stateful changes but State persists +/// - State changes +/// - initState() called when +/// - object inserted into WT +/// - dispose() called when +/// - object removed from WT permanently +/// - didChangeDependencies() called when +/// - State changes +/// - didUpdateWidget() called when +/// - Stateful config changes +/// - deactivate() called when +/// - object removed from WT temp +/// - setState() triggers +/// - State change +/// +/// +/// ## Widget, Elements and RenderObject Trees +/// +/// ### Widget Tree (WT) - Configure +/// +/// - Immutable description of what to show on screen +/// - Creates elements to mount in element tree +/// +/// ### Element Tree (ET) - Lifecycle +/// +/// - Instantiation of WT +/// - Mutable description of what to show on screen +/// +/// ### RenderObject Tree (RT) - Paint +/// +/// - What is currently shown on screen +/// - Handles size, layout and rendering +/// +/// ## Widget Keys +/// ### When to use +/// - When state needs to be preserved in widget tree +/// - e.g., Rearranging items in a list +/// ## Where to use +/// - Top of widget subtree which is being rearranged +/// - e.g., if items in list have padding, key should be assigned to padding +/// +/// ### Which to use +/// - Depends on state to be preserved +/// - ValueKey +/// - When state of each widget being rearranged is unique +/// - UniqueKey +/// - When state of widgets may not be unique +/// - ObjectKey +/// - When state attributes may be common amongst widgets, but combination of them is unique +/// - PageStorageKey +/// - Stores scroll location +/// - GlobalKey +/// - When widget needs to change parents without losing state +/// - e.g., same widget on two different pages +/// - When need to access info about widget in different part of the tree +/// - e.g., do not want other widgets to be able to access password widget +/// - NOTE: usually better way to avoid GlobalKey +/// - e.g., InheritedWidget, redux/block pattern +/// - DO NOT +/// - Set random number in key as everytime widget is rebuilt, a number different from element key is generated, making it redundant +/// +/// ### Mechanism +/// - Flutter's element-widget matching mechanism checks for same type +/// - Rearranging Stateless Widgets +/// 1. Stateless +/// - Rearranging Stateful Widgets +class HelpFlutter {} diff --git a/lib/inline_help/flutter/help_launcher_icons.dart b/lib/inline_help/flutter/help_launcher_icons.dart new file mode 100644 index 0000000..48bf67e --- /dev/null +++ b/lib/inline_help/flutter/help_launcher_icons.dart @@ -0,0 +1,34 @@ +/// ## Launcher +/// ### Name +/// #### Android +/// android/app/src/main/AndroidManifest.xml +/// ``` +/// ``` +/// #### iOS +/// ios/Runner/Info.plist +/// ``` +/// CFBundleDisplayName +/// your_app_name +/// CFBundleName +/// your_app_name +/// ``` +/// ### Icons +/// https://stackoverflow.com/questions/43928702/how-to-change-the-application-launcher-icon-on-flutter +/// #### Android +/// - Faced issues with getting flutter launcher icon packages to work for android background and foreground +/// - Manually setting the icons in android\app\src\main\res also does not affect the android icon foreground and background +/// - Need to open Android Studio > Image Studio > Configure Image Asset by going to android/app/src/main/res and right clicking -> New -> Image Asset +/// - This option does not appear if the gradle sync fails +/// - To fix this, open the build.gradle file in Android Studio, comment out the manifestPlaceholders section, then go to File > Sync Project with Gradle Files +/// - The option should now appear +/// +/// - Set icons manually instead +/// Flutter has its own default icon for every app in its Android and Ios folder so there are few steps that I would like to show to change the app icon. +/// #### iOS +/// https://appicon.co/ +/// - Go inside ios\Runner in your flutter app and there paste the Assets.xcassets content +/// Restart your emulator or rebuild your application 😁 +class HelpLauncherIcons {} diff --git a/lib/inline_help/flutter/help_ui_approach.dart b/lib/inline_help/flutter/help_ui_approach.dart new file mode 100644 index 0000000..afff8a0 --- /dev/null +++ b/lib/inline_help/flutter/help_ui_approach.dart @@ -0,0 +1,30 @@ +/// # UI Approach +/// +/// ## Declarative +/// +/// - what to show from state +/// - e.g., in Dart/Flutter: +/// +/// ``` +/// string = 'Hello World' +/// build() { +/// return Text(string) // text gets destroyed and rebuilt +/// } +/// ``` +/// +/// - Updating text on screen can be done by mutating state outside of build +/// - e.g., string = string + ! builds HelloWorld! +/// +/// ## Imperative +/// - how to show from state +/// - e.g., in Java/Android: +/// +/// ``` +/// build() { +/// return Text.setText('Hello World') // text does not get destroyed, value gets updated +/// } +/// ``` +/// +/// - Updating text on screen must be done by accessing current UI state before mutating UI +/// - e.g., Text.setText(Text.getText+"!") builds HelloWorld! +class HelpUIApproach {} diff --git a/lib/inline_help/state_management/help_change_notifier.dart b/lib/inline_help/state_management/help_change_notifier.dart new file mode 100644 index 0000000..d8c6754 --- /dev/null +++ b/lib/inline_help/state_management/help_change_notifier.dart @@ -0,0 +1,15 @@ +/// # Best practices with ChangeNotifer +/// +/// State in ChangeNotifiers should be init and disposed, e.g. +/// +/// ``` +/// class StateManagedChangeNotifier extends ChangeNotifier { +/// void initState() { +/// /// init class members here +/// } +/// void disposeState() { +/// /// dispose class members here +/// } +/// } +/// ``` +abstract class HelpChangeNotifier {} diff --git a/lib/inline_help/state_management/help_focus.dart b/lib/inline_help/state_management/help_focus.dart new file mode 100644 index 0000000..f7e0ad3 --- /dev/null +++ b/lib/inline_help/state_management/help_focus.dart @@ -0,0 +1,38 @@ +/// # Help with Focus System +/// +/// ## Overview +/// +/// - Directs keyboard input +/// - Terminology: +/// - Primary focus +/// - Farthest node away from root of tree that has focus +/// - Key events propagate from primary focus node to ancestors +/// - Focus chain +/// - Ordered list of nodes along branch from primary focus node to root +/// - Focus Traversal +/// - Moving focus from one node to another predictably +/// - E.g., pressing tab on keyboard +/// +/// ## Elements +/// +/// ### Focus Tree +/// +/// - Sparsely mirrors widget tree +/// - Contains focus nodes +/// +/// ### Focus Node +/// +/// - Represents widget that can receive focus +/// - Has focus: part of the focus chain +/// - Handles key events only when it has focus +/// +/// ### Focus Scope +/// +/// - Focus node which contains a group of focus nodes +/// - Limits focus to its nodes +/// - Contains info about which nodes were previously focused in its subtree +/// +/// ### Focus +/// - Widget that owns and manages a focus node +/// - +class HelpFocus {} diff --git a/lib/inline_help/state_management/help_provider.dart b/lib/inline_help/state_management/help_provider.dart new file mode 100644 index 0000000..413f934 --- /dev/null +++ b/lib/inline_help/state_management/help_provider.dart @@ -0,0 +1,97 @@ +/// # Help with Provider State Management +/// +/// ##### ChangeNotifier +/// +/// - Provides change notification to listeners/subscribers +/// - via notifyListeners() +/// - causes rebuild +/// - e.g., +/// +/// ``` +/// class ShoppingCartModel extends ChangeNotifier { +/// final List items = []; +/// void addToCart(Item item) { +/// items.add(item); +/// notifyListeners(); +/// } +/// } +/// ``` +/// +/// ##### ChangeNotifierProvider +/// - Provides instance of ChangeNotifier to descendants +/// - should not place higher than necessary to prevent pollution of scope +/// - e.g., +/// +/// ``` +/// void main() { +/// ChangeNotifierProvider( +/// create: (context) => ShoppingCartModel(), +/// child: constMyApp, +/// ) +/// } +/// ``` +/// +/// - Multiple providers possible: +/// +/// ``` +/// void main() { +/// runApp( +/// MultiProvider( +/// providers: [ +/// ChangeNotifierProvider(create: (context) => CartModel()), +/// Provider(create: (context) => SomeOtherClass()), +/// ], +/// child: const MyApp(), +/// ), +/// ); +/// } +/// ``` +/// +/// ##### Consumer +/// +/// - Grants access to provider state and triggers rebuild when provider state changes +/// - type of model must be specified, e.g., `` +/// - put Consumer as deep in tree as possible to prevent unnecessary rebuilds +/// - e.g., +/// +/// ``` +/// return Consumer( +/// builder: (context, cart, child) { +/// return Text("Total price: ${cart.totalPrice}"); +/// }, +/// ); +/// ``` +/// +/// - arguments: +/// - context +/// - ChangeNotifier instance +/// - Instance of requested provider type +/// - child +/// - Used for optimisation +/// - when there are expensive widgets that +/// - is under Consumer, and +/// - does not change with ChangeNotifier +/// - e.g., +/// +/// ``` +/// return Consumer( +/// builder: (context, cart, child) => Stack( +/// children: [ +/// /// Use SomeExpensiveWidget here, without rebuilding every time. +/// if (child != null) child, +/// Text("Total price: ${cart.totalPrice}"), +/// ], +/// ), +/// /// Build the expensive widget here. +/// child: const SomeExpensiveWidget(), +/// ); +/// ``` +/// +/// ##### Provider.of +/// +/// - Grants access to provider state without rebuild +/// +/// ``` +/// Provider.of(context, listen: false).removeAll(); +/// ``` +class HelpProvider {} diff --git a/lib/inline_help/state_management/help_state_management.dart b/lib/inline_help/state_management/help_state_management.dart new file mode 100644 index 0000000..02e09b2 --- /dev/null +++ b/lib/inline_help/state_management/help_state_management.dart @@ -0,0 +1,53 @@ +/// # Help with State Management in Flutter +/// +/// ## Terminology +/// ### Ephemeral State +/// - Definition +/// - UI or local state +/// - Contained in single widget +/// - e.g., animation progress, current page in pageview +/// - Use cases +/// - Does not change in complex ways +/// - Other parts of widget tree seldom require access +/// - Methods +/// - Stateful widget +/// ### App State +/// - Definition +/// - Shared across many widgets +/// - e.g., user prefs, login info, notifications, shopping cart, read/unread articles +/// - Use cases +/// - Required by many widgets +/// - Preserve some state between session, e.g., current page in page view +/// - Methods +/// - see 1.1.3 +/// - App State should be placed above widgets which use it +/// - Allows sub widgets to access parent state from anywhere in the tree without passing state down through multiple widgets +/// +/// ## Approaches +/// ### Provider +/// +/// - Recommended by Flutter; Easy to use and understandable +/// - Use Cases +/// - No strong reason to choose another approach +/// +/// ### InheritedWidget +/// - Low-level approach in widget tree +/// - Used by high-level approaches under the hood, e.g., InheritedWidget +/// #### InheritedWidget +/// - Provides children in subtree access to its state +/// - Components: +/// - State variables, +/// - e.g., final int itemsInCart; +/// - of method +/// - Provides exact instance of InheritedWidget to child +/// - updateShouldNotify method +/// - Controls when consumers are rebuilt +/// - Has oldWidget as argument, which allows comparing of current and previous state +/// #### Usage +/// +/// - InheritedWidget.of(context).stateVariableName +/// +/// ### Redux +/// ### Rx +/// ### Hooks +class HelpStateManagement {} diff --git a/pubspec.yaml b/pubspec.yaml index bc70b6d..fd7b26d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_dev_utils -description: Developer utils to make your life easier. -version: 0.0.1+1 +description: Developer utils to make your life easier; e.g. try handlers to easily find source of bug, help classes for code editor inline tips. +version: 0.0.1+2 homepage: https://github.com/Kek-Tech/flutter_dev_utils # publish_to: none # Remove this line if you wish to publish to pub.dev