Merge pull request #31 from Iconica-Development/doc/improve-documentation

doc: create documentation for files
This commit is contained in:
Gorter-dev 2024-03-27 09:48:36 +01:00 committed by GitHub
commit 597b5fa1f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 372 additions and 29 deletions

View file

@ -1,3 +1,7 @@
## 1.4.0
- Added CONTRIBUTING.md, documentation and updated flutter_input_library to 3.2.1
## 1.3.0 ## 1.3.0
- Field has been added so the user can provide it's current password for reauthentication. - Field has been added so the user can provide it's current password for reauthentication.

198
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,198 @@
# Contributing
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued.
See the [Table of Contents](#table-of-contents) for different ways to help and details about how we handle them.
Please make sure to read the relevant section before making your contribution.
It will make it a lot easier for us maintainers and smooth out the experience for all involved.
Iconica looks forward to your contributions. 🎉
## Table of contents
- [Code of conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Contributing code](#contributing-code)
## Code of conduct
### Legal notice
When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
All accepted pull requests and other additions to this project will be considered intellectual property of Iconica.
All repositories should be kept clean of jokes, easter eggs and other unnecessary additions.
## I have a question
If you want to ask a question, we assume that you have read the available documentation found within the code.
Before you ask a question, it is best to search for existing issues that might help you.
In case you have found a suitable issue but still need clarification, you can ask your question
It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following:
- Open an issue.
- Provide as much context as you can about what you're running into.
We will then take care of the issue as soon as possible.
## I want to contribute
### Reporting bugs
<!-- omit in toc -->
**Before submitting a bug report**
A good bug report shouldn't leave others needing to chase you up for more information.
Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report.
Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error.
- Also make sure to search the internet (including Stack Overflow) to see if users outside of Iconica have discussed the issue.
- Collect information about the bug:
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Time and date of occurance
- Describe the expected result and actual result
- Can you reliably reproduce the issue? And can you also reproduce it with older versions? Describe all steps that lead to the bug.
Once it's filed:
- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps.
If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for additional information.
- If the team is able to reproduce the issue, it will be moved into the backlog, as well as marked with a priority, and the issue will be left to be [implemented by someone](#contributing-code).
### Contributing code
When you start working on your contribution, make sure you are aware of the relevant documentation and the functionality of the component you are working on.
When writing code, follow the style guidelines set by Dart: [Effective Dart](https://Dart.dev/guides/language/effective-Dart). This contains most information you will need to write clean Dart code that is well documented.
**Documentation**
As Effective Dart indicates, documenting your public methods with Dart doc comments is recommended.
Aside from Effective Dart, we require specific information in the documentation of a method:
At the very least, your documentation should first name what the code does, then followed below by requirements for calling the method, the result of the method.
Any references to internal variables or other methods should be done through [var] to indicate a reference.
If the method or class is complex enough (determined by the reviewers) an example is required.
If unsure, add an example in the docs using code blocks.
For classes and methods, document the individual parameters with their implications.
> Tip: Remember that the shortest documentation can be written by having good descriptive names in the first place.
An example:
````Dart
library iconica_utilities.bidirectional_sorter;
part 'sorter.Dart';
part 'enum.Dart';
/// Generic sort method, allow sorting of list with primitives or complex types.
/// Uses [SortDirection] to determine the direction, either Ascending or Descending,
/// Gets called on [List] toSort of type [T] which cannot be shorter than 2.
/// Optionally for complex types a [Comparable] [Function] can be given to compare complex types.
/// ```
/// List<TestObject> objects = [];
/// for (int i = 0; i < 10; i++) {
/// objects.add(TestObject(name: "name", id: i));
/// }
///
/// sort<TestObject>(
/// SortDirection.descending, objects, (object) => object.id);
///
/// ```
/// In the above example a list of TestObjects is created, and then sorted in descending order.
/// If the implementation of TestObject is as following:
/// ```
/// class TestObject {
/// final String name;
/// final int id;
///
/// TestObject({required this.name, required this.id});
/// }
/// ```
/// And the list is logged to the console, the following will appear:
/// ```
/// [name9, name8, name7, name6, name5, name4, name3, name2, name1, name0]
/// ```
void sort<T>(
/// Determines the sorting direction, can be either Ascending or Descending
SortDirection sortDirection,
/// Incoming list, which gets sorted
List<T> toSort, [
/// Optional comparable, which is only necessary for complex types
SortFieldGetter<T>? sortValueCallback,
]) {
if (toSort.length < 2) return;
assert(
toSort.whereType<Comparable>().isNotEmpty || sortValueCallback != null);
BidirectionalSorter<T>(
sortInstructions: <SortInstruction<T>>[
SortInstruction(
sortValueCallback ?? (t) => t as Comparable, sortDirection),
],
).sort(toSort);
}
/// same functionality as [sort] but with the added functionality
/// of sorting multiple values
void sortMulti<T>(
/// Incoming list, which gets sorted
List<T> toSort,
/// list of comparables to sort multiple values at once,
/// priority based on index
List<SortInstruction<T>> sortValueCallbacks,
) {
if (toSort.length < 2) return;
assert(sortValueCallbacks.isNotEmpty);
BidirectionalSorter<T>(
sortInstructions: sortValueCallbacks,
).sort(toSort);
}
````
**Tests**
For each public method that was created, excluding widgets, which contains any form of logic (e.g. Calculations, predicates or major side-effects) tests are required.
A set of tests is written for each method, covering at least each path within the method. For example:
```Dart
void foo() {
try {
var bar = doSomething();
if (bar) {
doSomethingElse();
} else {
doSomethingCool();
}
} catch (_) {
displayError();
}
}
```
The method above should result in 3 tests:
1. A test for the path leading to displayError by the cause of an exception
2. A test for if bar is true, resulting in doSomethingElse()
3. A test for if bar is false, resulting in the doSomethingCool() method being called.
This means that we require 100% coverage of each method you test.

View file

@ -31,6 +31,7 @@ Underneath are all paramters, of the 'ProfilePage' widget, listed with an explan
| itemBuilderOptions | The options used by the standard itemBuilder to alter the function and style of the textfields | | itemBuilderOptions | The options used by the standard itemBuilder to alter the function and style of the textfields |
| prioritizedItems | The items that are displayed at the top of the page. Before all the other items in the list and the default items | | prioritizedItems | The items that are displayed at the top of the page. Before all the other items in the list and the default items |
By default input fields are saved after pressing 'enter' inside of the input field.
## Issues ## Issues
@ -38,7 +39,7 @@ Please file any issues, bugs or feature request as an issue on our [GitHub](http
## Want to contribute ## Want to contribute
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_profile/pulls). If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_profile/pulls).
## Author ## Author

View file

@ -122,11 +122,11 @@ packages:
dependency: transitive dependency: transitive
description: description:
path: "." path: "."
ref: "3.1.0" ref: "3.2.1"
resolved-ref: "5fca291c5e79c9ad6dad500e4ea5d9b628ee0f5d" resolved-ref: fddf100fb0aaeff3d6171f58c403d811fab80346
url: "https://github.com/Iconica-Development/flutter_input_library" url: "https://github.com/Iconica-Development/flutter_input_library"
source: git source: git
version: "3.1.0" version: "3.2.1"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -141,7 +141,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "1.2.0" version: "1.4.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -171,6 +171,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.1" version: "0.18.1"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
url: "https://pub.dev"
source: hosted
version: "2.0.1"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
url: "https://pub.dev"
source: hosted
version: "2.0.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@ -183,26 +207,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16" version: "0.12.16+1"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.8.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.11.0"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:
@ -215,10 +239,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.9.0"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -408,14 +432,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
web: vm_service:
dependency: transitive dependency: transitive
description: description:
name: web name: vm_service
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.0" version: "13.0.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -433,5 +457,5 @@ packages:
source: hosted source: hosted
version: "0.2.0+2" version: "0.2.0+2"
sdks: sdks:
dart: ">=3.2.0-194.0.dev <4.0.0" dart: ">=3.2.0-0 <4.0.0"
flutter: ">=3.10.0" flutter: ">=3.10.0"

View file

@ -25,13 +25,32 @@ class User {
imageUrl: data['image_url'], imageUrl: data['image_url'],
profileData: data['profile_data'], profileData: data['profile_data'],
); );
/// The first name of the user.
String? firstName; String? firstName;
/// The last name of the user.
String? lastName; String? lastName;
/// The image of the user, stored as Uint8List.
Uint8List? image; Uint8List? image;
/// The URL of the user's image.
String? imageUrl; String? imageUrl;
/// Additional profile data for the user.
ProfileData? profileData; ProfileData? profileData;
/// The display name of the user, which is a combination of
/// the first name and the last name.
/// If the first name or the last name is null,
/// an empty string is used instead.
String get displayName => '${firstName ?? ''} ${lastName ?? ''}'; String get displayName => '${firstName ?? ''} ${lastName ?? ''}';
/// The initials of the user, which are the first characters
/// of the first name and the last name.
/// If the first name or the last name is null or empty,
/// an empty string is used instead.
String get initials => String get initials =>
'${(firstName?.isNotEmpty ?? false) ? firstName![0] : ''}' '${(firstName?.isNotEmpty ?? false) ? firstName![0] : ''}'
'${(lastName?.isNotEmpty ?? false) ? lastName![0] : ''}'; '${(lastName?.isNotEmpty ?? false) ? lastName![0] : ''}';

View file

@ -14,8 +14,13 @@ class Avatar extends StatelessWidget {
this.avatarBackgroundColor, this.avatarBackgroundColor,
}); });
/// The user object containing user information.
final User? user; final User? user;
/// Size of the avatar.
final double size; final double size;
/// Background color of the avatar.
final Color? avatarBackgroundColor; final Color? avatarBackgroundColor;
@override @override
@ -54,6 +59,7 @@ class Avatar extends StatelessWidget {
); );
} }
/// Returns the image provider based on user's image or image URL.
ImageProvider? _getImageProvider(User? user) { ImageProvider? _getImageProvider(User? user) {
if (user?.image != null) { if (user?.image != null) {
return MemoryImage(user!.image!); return MemoryImage(user!.image!);
@ -63,6 +69,8 @@ class Avatar extends StatelessWidget {
return null; return null;
} }
/// Generates a color based on the initials of the user's
/// first name and last name.
Color _generateColorWithIntials(String? firstName, String? lastName) { Color _generateColorWithIntials(String? firstName, String? lastName) {
var idFirstName = 0; var idFirstName = 0;
var idLastName = 0; var idLastName = 0;

View file

@ -18,14 +18,27 @@ class AvatarWrapper extends StatelessWidget {
this.avatarBackgroundColor, this.avatarBackgroundColor,
}); });
/// The user object containing user information.
final User user; final User user;
/// Custom widget to be used as an avatar.
final Widget? customAvatar; final Widget? customAvatar;
/// Background color of the avatar.
final Color? avatarBackgroundColor; final Color? avatarBackgroundColor;
/// Whether to show the user's name beneath the avatar.
final bool showName; final bool showName;
/// Padding around the avatar and the name.
final EdgeInsets padding; final EdgeInsets padding;
final TextStyle? textStyle;
/// Size of the avatar.
final double size; final double size;
/// Style for the user's name.
final TextStyle? textStyle;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var avatar = customAvatar ?? var avatar = customAvatar ??
@ -43,8 +56,8 @@ class AvatarWrapper extends StatelessWidget {
padding: padding, padding: padding,
child: Flexible( child: Flexible(
child: Text( child: Text(
style: textStyle,
user.displayName, user.displayName,
style: textStyle,
), ),
), ),
), ),

View file

@ -44,18 +44,38 @@ class ItemList {
}); });
} }
} }
/// Gets the map of item keys and their corresponding widgets.
Map<String, Widget> getItemList() => widgets; Map<String, Widget> getItemList() => widgets;
/// Map containing item keys and their values.
final Map<String, dynamic> items; final Map<String, dynamic> items;
/// Map containing item keys and their types.
final Map<String, dynamic> typeMap; final Map<String, dynamic> typeMap;
/// Function to update the profile with a specific item's value.
final Function(String, String?) updateProfile; final Function(String, String?) updateProfile;
/// Function to save the profile after an item value is updated.
final Function() saveProfile; final Function() saveProfile;
/// Builder for custom item widgets.
final ItemBuilder? itemBuilder; final ItemBuilder? itemBuilder;
/// Options for the item builder.
final ItemBuilderOptions? itemBuilderOptions; final ItemBuilderOptions? itemBuilderOptions;
/// Global key for the form associated with the item list.
final GlobalKey<FormState> formKey; final GlobalKey<FormState> formKey;
/// Map containing item keys and their corresponding widgets.
Map<String, Widget> widgets = {}; Map<String, Widget> widgets = {};
/// `builder` is an instance of `ItemBuilder` which is used
/// to build the items in the list.
/// If `itemBuilderOptions` is not provided, a default
/// `ItemBuilderOptions` instance is used.
late ItemBuilder builder = ItemBuilder( late ItemBuilder builder = ItemBuilder(
options: itemBuilderOptions ?? ItemBuilderOptions(), options: itemBuilderOptions ?? ItemBuilderOptions(),
); );

View file

@ -13,12 +13,25 @@ class ChangePassword extends StatefulWidget {
super.key, super.key,
}); });
/// Configuration for changing password.
final ChangePasswordConfig config; final ChangePasswordConfig config;
/// Options for wrapping the items.
final WrapViewOptions? wrapViewOptions; final WrapViewOptions? wrapViewOptions;
final ItemBuilder? itemBuilder;
final ItemBuilderOptions? itemBuilderOptions; /// Builder for wrapping items.
final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder; final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder;
/// Builder for creating items.
final ItemBuilder? itemBuilder;
/// Options for item builder.
final ItemBuilderOptions? itemBuilderOptions;
/// Styling options for the widget.
final ProfileStyle style; final ProfileStyle style;
/// Profile service for managing user profile.
final ProfileService service; final ProfileService service;
@override @override

View file

@ -153,9 +153,19 @@ class WrapViewOptions {
this.runSpacing, this.runSpacing,
this.clipBehavior, this.clipBehavior,
}); });
/// The direction to use as the main axis.
Axis? direction; Axis? direction;
/// The distance between adjacent children in the cross axis.
double? spacing; double? spacing;
double? runSpacing;
Clip? clipBehavior; /// How the children should be placed along the main axis.
WrapAlignment? wrapAlignment; WrapAlignment? wrapAlignment;
/// The distance between adjacent children in the main axis.
double? runSpacing;
/// Determines how visual overflow should be handled.
Clip? clipBehavior;
} }

View file

@ -38,22 +38,55 @@ class ProfileWrapper extends StatefulWidget {
super.key, super.key,
}); });
/// The user object containing user information.
final User user; final User user;
/// The service for managing user profile.
final ProfileService service; final ProfileService service;
/// The styling options for the profile.
final ProfileStyle style; final ProfileStyle style;
/// Custom avatar widget.
final Widget? customAvatar; final Widget? customAvatar;
/// Flag to show or hide the avatar.
final bool showAvatar; final bool showAvatar;
/// Background color for the avatar.
final Color? avatarBackgroundColor; final Color? avatarBackgroundColor;
/// Text for the bottom action.
final String? bottomActionText; final String? bottomActionText;
/// Builder for creating items.
final ItemBuilder? itemBuilder; final ItemBuilder? itemBuilder;
final WrapViewOptions? wrapViewOptions;
final Function() rebuild; /// Options for item builder.
final ItemBuilderOptions? itemBuilderOptions; final ItemBuilderOptions? itemBuilderOptions;
/// Options for wrapping the view.
final WrapViewOptions? wrapViewOptions;
/// Callback to rebuild the widget.
final Function() rebuild;
/// Flag to show default items.
final bool showDefaultItems; final bool showDefaultItems;
/// Flag to show items.
final bool showItems; final bool showItems;
/// Builder for wrapping items.
final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder; final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder;
final Map<String, Widget>? extraWidgets;
/// Key for the form.
final GlobalKey<FormState>? formKey; final GlobalKey<FormState>? formKey;
/// Additional widgets to be displayed.
final Map<String, Widget>? extraWidgets;
/// Configuration for changing password.
final ChangePasswordConfig changePasswordConfig; final ChangePasswordConfig changePasswordConfig;
/// Map keys of items that should be shown first before the default items and /// Map keys of items that should be shown first before the default items and

View file

@ -1,6 +1,6 @@
name: flutter_profile name: flutter_profile
description: Flutter profile package description: Flutter profile package
version: 1.3.0 version: 1.4.0
repository: https://github.com/Iconica-Development/flutter_profile repository: https://github.com/Iconica-Development/flutter_profile
publish_to: none publish_to: none
@ -15,7 +15,7 @@ dependencies:
flutter_input_library: flutter_input_library:
git: git:
url: https://github.com/Iconica-Development/flutter_input_library url: https://github.com/Iconica-Development/flutter_input_library
ref: 3.0.1 ref: 3.2.1
flutter: flutter:
sdk: flutter sdk: flutter