diff --git a/.gitignore b/.gitignore index 37e175bc..f9b92095 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,47 @@ # File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig +# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,android,androidstudio,dart,fastlane,firebase,flutter,java,jetbrains+all,kotlin,objective-c,swift,xcode +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,android,androidstudio,dart,fastlane,firebase,flutter,java,jetbrains+all,kotlin,objective-c,swift,xcode -# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,linux,windows -# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,dart,flutter,linux,windows +### Android ### +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ +*.iml +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof + +### Android Patch ### +gen-external-apklibs + +# Replacement of .externalNativeBuild directories introduced +# with Android Studio 3.5. ### Dart ### # See https://www.dartlang.org/guides/libraries/private-files @@ -9,22 +49,17 @@ # Files and directories created by pub .dart_tool/ .packages -build/ # If you're building an application, you may want to check-in your pubspec.lock pubspec.lock -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -doc/api/ - # dotenv environment variables file .env* # Avoid committing generated Javascript files: *.dart.js -*.info.json # Produced by the --dump-info flag. -*.js # When generated by dart2js. Don't specify *.js if your - # project includes source files written in JavaScript. +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your +# project includes source files written in JavaScript. *.js_ *.js.deps *.js.map @@ -36,15 +71,47 @@ doc/api/ # dotenv environment variables file .env +### fastlane ### +# fastlane - A streamlined workflow tool for Cocoa deployment +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +# fastlane specific +**/fastlane/report.xml + +# deliver temporary files +**/fastlane/Preview.html + +# snapshot generated screenshots +**/fastlane/screenshots + +# scan temporary files +**/fastlane/test_output + +# Fastlane.swift runner binary +**/fastlane/FastlaneRunner + +### Firebase ### +.idea +**/node_modules/* +**/.firebaserc + +### Firebase Patch ### +.runtimeconfig.json +.firebase/ + ### Flutter ### # Flutter/Dart/Pub related **/doc/api/ -.fvm/ +.fvm/flutter_sdk .pub-cache/ .pub/ coverage/ lib/generated_plugin_registrant.dart -# For library packages, don’t commit the pubspec.lock file. +# For library packages, don't commit the pubspec.lock file. # Regenerating the pubspec.lock file lets you test your package against the latest compatible versions of its dependencies. # See https://dart.dev/guides/libraries/private-files#pubspeclock #pubspec.lock @@ -95,20 +162,131 @@ lib/generated_plugin_registrant.dart !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -### Linux ### -*~ +### Java ### +# Compiled class file +*.class -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* +# Log file -# KDE directory preferences -.directory +# BlueJ files +*.ctxt -# Linux trash folder which might appear on any partition or disk -.Trash-* +# Mobile Tools for Java (J2ME) +.mtj.tmp/ -# .nfs files are created when an open file is removed but is still being accessed -.nfs* +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### JetBrains+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### Kotlin ### +# Compiled class file + +# Log file + +# BlueJ files + +# Mobile Tools for Java (J2ME) + +# Package Files # + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml ### macOS ### # General @@ -119,7 +297,6 @@ lib/generated_plugin_registrant.dart # Icon must end with two \r Icon - # Thumbnails ._* @@ -143,6 +320,116 @@ Temporary Items # iCloud generated files *.icloud +### Objective-C ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Objective-C Patch ### + +### Swift ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + ### VisualStudioCode ### .vscode/* !.vscode/settings.json @@ -162,35 +449,129 @@ Temporary Items .history .ionide -# Support for Project snippet scope +### Xcode ### -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db +## Xcode 8 and earlier -# Dump file -*.stackdump +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings -# Folder config file -[Dd]esktop.ini +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# Built application files +*.ap_ +*.aab -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp +# Files for the ART/Dalvik VM +*.dex -# Windows shortcuts -*.lnk +# Java class files -# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,linux,windows +# Generated files +bin/ +gen/ + +# Gradle files +.gradle + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +.navigation/ +*.ipr +*~ +*.swp + +# Keystore files + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# NDK +obj/ + +# IntelliJ IDEA +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/assetWizardSettings.xml +.idea/gradle.xml +.idea/jarRepositories.xml +.idea/navEditor.xml + +# Legacy Eclipse project files +.classpath +.project +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) + +# Package Files # + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,android,androidstudio,dart,fastlane,firebase,flutter,java,jetbrains+all,kotlin,objective-c,swift,xcode # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) @@ -200,4 +581,4 @@ google-services.json pubspec_overrides.yaml # Mason -.mason/ \ No newline at end of file +.mason/ diff --git a/.pubignore b/.pubignore new file mode 100644 index 00000000..43c82d3c --- /dev/null +++ b/.pubignore @@ -0,0 +1,5 @@ +new_version.sh +.latest_version +.vscode/ +example/ +models/ diff --git a/AUTHORS b/AUTHORS index f9506138..a1c2a78d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,5 +4,5 @@ # Name/Organization Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file +Hugo Pointcheval +Malo Léon diff --git a/README.md b/README.md index 410ef3c4..8b78891e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- - - +

Wyatt Packages

- - Style: Wyatt Analysis - - - Maintained with Melos - + Style: Wyatt Analysis + Maintained with Melos

--- @@ -38,12 +32,40 @@ --- + + + + +- [About](#about) +- [Contribution](#contribution) + - [Prerequisite](#prerequisite) + - [Create a new package](#create-a-new-package) + - [Naming](#naming) + - [Create issues](#create-issues) + - [Branches](#branches) + - [Commits](#commits) + - [Before pushing](#before-pushing) + - [Merge your work](#merge-your-work) + - [Update version.](#update-version) + - [Publish your package](#publish-your-package) + - [Badging](#badging) +- [Usage](#usage) +- [Simple work flow diagramm](#simple-work-flow-diagramm) +- [Status](#status) +- [License](#license) + + + +--- + ## About Here is a set of [Flutter plugins](https://flutter.io/platform-plugins/) that enhance your applications. [Flutter](https://flutter.dev) is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop using a single codebase. It is used by developers and organizations worldwide and is free and open-source. +Those packages are developed by [Wyatt Studio](https://wyatt-studio.fr) and are available exclusively on this repository. + --- ## Contribution @@ -77,9 +99,9 @@ dart pub global activate mason_cli brew install lcov ``` -- genhtml. Used to convert coverage data into html pages. +* genhtml. Used to convert coverage data into html pages. -After installation of all these packages, the project can be bootstrapped using the command `melos bs`. +After installation of all these packages, the project can be bootstrapped using the command `melos bs` . ### Create a new package @@ -87,9 +109,11 @@ Create a new package in `packages/` folder. To create a new package in the packages/ folder, run the following command in the terminal: ```shell -mason make wyatt_package --package_name wyatt_ --description A new Wyatt package --flutter_only false +mason make wyatt_package_template --package_name --description A new Wyatt package --flutter false ``` +> Browse our [bricks](https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-bricks) for more information. + The variable in the above command is important and must be clear and understandable. After creating the package, bootstrap the project with the `melos bs` command. @@ -101,70 +125,63 @@ It have to be clear and intelligible. 1. You must use underscores in the name. 2. You must use the wyatt prefix for the package name. -3. You must name the example with a specific name. -For example, if the name is "CRUD BLOC," the following naming conventions should be used: +For example, if the name is `CRUD BLOC` the following naming conventions should be used: -1. name: crud_bloc -2. package name: wyatt_crud_bloc -3. example name: crud_bloc_example +1. package name: `wyatt_crud_bloc` +2. example name: `example` ### Create issues -Create an issue for each specific feature or task you want to work on and label it correctly using the following format: +Create an issue for each specific feature or task you want to work on and label it correctly using the following labels: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/labels. -``` -Type(scope): issue. -``` - -For example, on notification bloc package : - -- `Feature(notification_bloc): add firebase messaging data source.` -- `Test(notification_bloc): add test for pushwoosh datasource.` +For example, if you want to work on the `i18n` package, you should create an issue with the `i18n` label. ### Branches -The master branch is protected and cannot be pushed to directly. Please create a separate branch for each feature or task, with a name that corresponds to the related issue. The branch name should follow this format: +The `master` branch is protected and cannot be pushed to directly. Please create a separate branch for each feature or task, with a name that corresponds to the related issue. The branch name should follow this format: -`type(scope):issue` + `scope/type/short-name` -Example : -For the issue: - -- `Feature(notification_bloc): add firebase messaging data source.` - -The related branch should be named: - -- `notification_bloc/feat/add_firebase_messaging_data_source` +For example, if you are working on the `i18n` package and you want to add a new feature, you should create a branch named `i18n/feat/add-new-feature` . ### Commits See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -tl;dr : `type(scope): description #issue`. +tldr : `type(scope): description #issue` . + Here allowed values: -- **feat** for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version. -- **fix** for a bug fix for the user, not a fix to a build script. Such commit will trigger a release bumping a PATCH version. -- **perf** for performance improvements. Such commit will trigger a release bumping a PATCH version. -- **docs** for changes to the documentation. -- **style** for formatting changes, missing semicolons, etc. -- **refactor** for refactoring production code, e.g. renaming a variable. -- **test** for adding missing tests, refactoring tests; no production code change. -- **build** for updating build configuration, development tools or other changes irrelevant to the user. +* **build** for updating build configuration, development tools or other changes irrelevant to the user. +* **ci** for changes to our CI configuration files and scripts. +* **docs** for changes to documentation. +* **feat** for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version. +* **fix** for a bug fix for the user, not a fix to a build script. Such commit will trigger a release bumping a PATCH version. +* **perf** for performance improvements. Such commit will trigger a release bumping a PATCH version. +* **refactor** for refactoring production code, e.g. renaming a variable. +* **style** for formatting changes, missing semicolons, etc. +* **test** for adding missing tests, refactoring tests; no production code change. +* **chore** for updating grunt tasks etc; no production code change. + +> Check `.pre-commit-config.yaml` and [pre-commit](https://pre-commit.com/) for more information about commit hooks. Some examples : -- `feat(auth): add AWS support. (#31)` = add a feature in authentication_bloc package, linked to the 31st issue. -- `docs: update readme.` = update **this** readme file. -- `fix(crud)!: fix bug in awesome() function. (#32)` = fix a bug, `!` is important and indicate `BREAKING CHANGES` linked with the 32nd issue. +* `feat(auth): add AWS support. (#31)` = add a feature in authentication_bloc package, linked to the 31st issue. +* `docs: update readme.` = update **this** readme file. +* `fix(crud)!: fix bug in awesome() function. (closes #32)` = fix a bug, `!` is important and indicate `BREAKING CHANGES` linked with the 32nd issue. -When you have completed your development work and are ready to resolve the related issue, you can close it via your commit message by including (close #issue_number). For example: +When you have completed your development work and are ready to resolve the related issue, you can close it via your commit message by including (closes #issue_number). For example: ```shell -feat(auth): add AWS support. (close #31) +feat(auth): add AWS support. (closes #31) ``` +> You can use `close` , `closes` , `closed` , `fix` , `fixes` , `fixed` , `resolve` , `resolves` or `resolved` . + +#### Before pushing + ```shell melos run test:all # this will run all tests in this project melos run gen-coverage # this will generate coverage report @@ -176,19 +193,19 @@ melos run publish # this will publish packages Please note that the issue will only be closed after it has been merged into the master branch. Before closing the issue, it is important to verify that all tests have been run and that coverage has been updated. -#### Merge your work +### Merge your work When you have completed your work and closed the related issue, it's possible that some changes may have been made to the master branch in the meantime. To maintain a clean Git history, it's recommended to rebase before creating a change request (pull request). Two situations : -- You haven't created a branch yet and have made local commits: +* You haven't created a branch yet and have made local commits: ```shell git pull --rebase ``` -- You are already working on a branch: +* You are already working on a branch: ```shell git rebase -i master @@ -198,7 +215,7 @@ It's recommended to use the `--fixup` option during the interactive rebase to ke Once you have rebased, you can create a pull request, receive the necessary approvals, and then merge your work. And with that, you're done! 🎉 -#### Update version. +### Update version. When your work has been merged into the master branch, it's time to update the package version. To update only your specific package, use the --scope option. For example, after merging changes into the `wyatt_notification_bloc` package, you can run the following command: @@ -214,32 +231,38 @@ You can then verify that all packages and their tests are working correctly by r melos run test:all ``` -#### Publish your package +### Publish your package -If package is ready for procution, publish it runnig : +If package is ready for production, publish it by running the following command : ```shell melos publish --scope"*package*" ``` -#### Badging +### Badging In the package `readme.md` file, please specify the supported SDK: ![SDK: Dart & Flutter](https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square) ```markdown + ![SDK: Dart & Flutter](https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square) + ``` or -![SDK: Dart](https://img.shields.io/badge/SDK-Dart-blue?style=flat-square) +![SDK: Flutter](https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square) ```markdown -![SDK: Dart](https://img.shields.io/badge/SDK-Dart-blue?style=flat-square) + +![SDK: Flutter](https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square) + ``` +> Some packages requires Flutter, so please specify it. + --- ## Usage @@ -251,11 +274,20 @@ dependencies: wyatt_analysis: git: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.0.0 + ref: wyatt_analysis-v2.4.1 path: packages/wyatt_analysis ``` -Here you can change `package name` and `package version`. +or the hosted version : + +```yaml +dependencies: + wyatt_analysis: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 2.4.1 +``` + +Here you can change `package name` and `package version` . --- @@ -263,10 +295,32 @@ Here you can change `package name` and `package version`. To sum up, here a simple work flow diagramm. -![Dev Wokflow](doc/workflow.svg) +```plantuml +@startuml Simple Developpment Workflow +start +:Create an issue; +:Create branch related to the issue; +repeat :Commit related to the issue; +repeat while (feature is done) +:Update coverage; +:Close issue via last commit; +:Rebase from `master`; +:Create pull request; +:Merge branches; +:Update version; +:Publish package; +stop +@enduml +``` ## Status ![Status: Experimental](https://img.shields.io/badge/Status-WIP-red?style=flat-square) This repository is maintained by Wyatt Studio but work is in progress. + +## License + +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) + +Thoses packages are licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details. diff --git a/doc/work_flow.puml b/doc/work_flow.puml deleted file mode 100644 index 5e6e983d..00000000 --- a/doc/work_flow.puml +++ /dev/null @@ -1,15 +0,0 @@ -@startuml Simple Developpment Workflow -start -:Create an issue; -:Create branch related to the issue; -repeat :Commit related to the issue; -repeat while (feature is done) -:Update coverage; -:Close issue via last commit; -:Rebase from `master`; -:Create pull request; -:Merge branches; -:Update version; -:Publish package; -stop -@enduml \ No newline at end of file diff --git a/doc/workflow.svg b/doc/workflow.svg deleted file mode 100644 index c8443191..00000000 --- a/doc/workflow.svg +++ /dev/null @@ -1,25 +0,0 @@ -Create an issueCreate branch related to the issueCommit related to the issuefeature is doneUpdate coverageClose issue via last commitRebase from `master`Create pull requestMerge branchesUpdate versionPublish package \ No newline at end of file diff --git a/packages/wyatt_analysis/.gitignore b/packages/wyatt_analysis/.gitignore deleted file mode 100644 index 65c34dc8..00000000 --- a/packages/wyatt_analysis/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_analysis/.gitignore b/packages/wyatt_analysis/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_analysis/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_analysis/.pubignore b/packages/wyatt_analysis/.pubignore deleted file mode 100644 index e2355bec..00000000 --- a/packages/wyatt_analysis/.pubignore +++ /dev/null @@ -1,2 +0,0 @@ -new_version.sh -.latest_version \ No newline at end of file diff --git a/packages/wyatt_analysis/.pubignore b/packages/wyatt_analysis/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_analysis/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_analysis/AUTHORS b/packages/wyatt_analysis/AUTHORS deleted file mode 100644 index b6d7d765..00000000 --- a/packages/wyatt_analysis/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_analysis/AUTHORS b/packages/wyatt_analysis/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_analysis/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_analysis/LICENSE b/packages/wyatt_analysis/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_analysis/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_analysis/LICENSE b/packages/wyatt_analysis/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_analysis/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_analysis/README.md b/packages/wyatt_analysis/README.md index 28b5244d..95d85e02 100644 --- a/packages/wyatt_analysis/README.md +++ b/packages/wyatt_analysis/README.md @@ -20,7 +20,7 @@ ![SDK: Dart & Flutter](https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square) -This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.4.1.yaml**. +This package provides lint rules for Dart and Flutter which are used at [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.4.1.yaml**. **Note**: This package was heavily inspired by [pedantic](https://github.com/dart-lang/pedantic), [Very Good Analysis](https://github.com/VeryGoodOpenSource/very_good_analysis) and the official [flutter_lints](https://pub.dev/packages/flutter_lints). diff --git a/packages/wyatt_architecture/.gitignore b/packages/wyatt_architecture/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_architecture/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_architecture/.gitignore b/packages/wyatt_architecture/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_architecture/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_architecture/.pubignore b/packages/wyatt_architecture/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_architecture/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_architecture/AUTHORS b/packages/wyatt_architecture/AUTHORS deleted file mode 100644 index f9506138..00000000 --- a/packages/wyatt_architecture/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file diff --git a/packages/wyatt_architecture/AUTHORS b/packages/wyatt_architecture/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_architecture/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_architecture/LICENSE b/packages/wyatt_architecture/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_architecture/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_architecture/LICENSE b/packages/wyatt_architecture/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_architecture/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_architecture/README.md b/packages/wyatt_architecture/README.md index 871b2e08..e077fbec 100644 --- a/packages/wyatt_architecture/README.md +++ b/packages/wyatt_architecture/README.md @@ -1,5 +1,5 @@ -# Flutter - Wyatt Architecture +# Wyatt Architecture

- - - Style: Wyatt Analysis - - - SDK: Flutter + Style: Wyatt Analysis + SDK: Dart & Flutter

-The Wyatt Architecture for Flutter. +The Wyatt Architecture for Flutter. Contains useful classes to help you to create a clean architecture following the Wyatt Architecture. (core, data, domain, presentation). ## Features -- Usecase -- Repository -- DataSource -- Entity +* Usecase +* Repository +* DataSource +* Entity ## Usage @@ -79,7 +75,7 @@ And finaly create your different usecases : Several use cases are supported : -- Classic usecase : +* Classic usecase : ```dart class Test extends AsyncUseCase>> { @@ -109,7 +105,6 @@ class SearchPhotos extends AsyncUseCase>> { return photos; } - @override FutureOr onStart(QueryParameters? params) { if(params.start == null || params.limit == null){ @@ -120,9 +115,9 @@ class SearchPhotos extends AsyncUseCase>> { } ``` -You can implement error scenarios overriding `onError`, or check postconditions by overriding `onComplete` . +You can implement error scenarios overriding `onError` , or check postconditions by overriding `onComplete` . -- Stream usecase : +* Stream usecase : ```dart class SearchPhotos extends StreamUseCase>> { @@ -139,9 +134,9 @@ class SearchPhotos extends StreamUseCase>> { } ``` -On this case, observers allow you to add alternative scénarios when data changed, overriding `onData` or `onDone`. +On this case, observers allow you to add alternative scenarios when data changed, overriding `onData` or `onDone` . -Please note that to use handlers, call `call` method and not `execute`. +Please note that to use handlers, call `call` method and not `execute` . > In fact, here we need a new parameter object, so let's create it: @@ -156,7 +151,7 @@ class QueryParameters { ### Data -We start by creating models for photos and list of photos. You can use `freezed`. The `PhotoModel` extends `Photo` with some de/serializer capabilities. And those are used only in data layer. +We start by creating models for photos and list of photos. You can use `freezed` . The `PhotoModel` extends `Photo` with some de/serializer capabilities. And those are used only in data layer. Then implements your data sources: diff --git a/packages/wyatt_architecture/analysis_options.yaml b/packages/wyatt_architecture/analysis_options.yaml index 9f5b6860..53aca98a 100644 --- a/packages/wyatt_architecture/analysis_options.yaml +++ b/packages/wyatt_architecture/analysis_options.yaml @@ -1,21 +1,17 @@ -# Copyright (C) 2022 WYATT GROUP +# Copyright (C) 2023 WYATT GROUP # Please see the AUTHORS file for details. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -include: package:wyatt_analysis/analysis_options.flutter.yaml - -analyzer: - exclude: "!example/**" +include: package:wyatt_analysis/analysis_options.yaml diff --git a/packages/wyatt_architecture/example/lib/core/dependency_injection/get_it.dart b/packages/wyatt_architecture/example/lib/core/dependency_injection/get_it.dart index e43a12a1..a3e2bc25 100644 --- a/packages/wyatt_architecture/example/lib/core/dependency_injection/get_it.dart +++ b/packages/wyatt_architecture/example/lib/core/dependency_injection/get_it.dart @@ -52,13 +52,13 @@ abstract class GetItInitializer { ) ..registerLazySingleton(() { final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( - protocol: Protocols.https, - authority: 'jsonplaceholder.typicode.com', - ), - ) - .addMiddleware(BodyToJsonMiddleware()); + ..addMiddleware( + const UriPrefixMiddleware( + protocol: Protocols.https, + authority: 'jsonplaceholder.typicode.com', + ), + ) + ..addMiddleware(const BodyToJsonMiddleware()); return MiddlewareClient(pipeline: pipeline); }) ..registerLazySingleton( diff --git a/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart b/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart index d7a5aaf3..274502f1 100644 --- a/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart +++ b/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart @@ -36,7 +36,7 @@ class PhotoRepositoryImpl extends PhotoRepository { @override FutureOrResult addPhotoToFavorites(Photo photo) => Result.tryCatchAsync( () => _favoriteLocalDataSource.addPhotoToFavorites(photo), - (error) => ClientException('Cannot add photo to favorites.'), + (error) => const ClientException('Cannot add photo to favorites.'), ); @override @@ -63,14 +63,14 @@ class PhotoRepositoryImpl extends PhotoRepository { FutureOrResult> getAllAlbums({int? start, int? limit}) => Result.tryCatchAsync( () => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit), - (error) => ServerException('Cannot retrieve all albums.'), + (error) => const ServerException('Cannot retrieve all albums.'), ); @override FutureOrResult> getAllPhotos({int? start, int? limit}) async => Result.tryCatchAsync( () => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit), - (error) => ServerException('Cannot retrieve all photos.'), + (error) => const ServerException('Cannot retrieve all photos.'), ); @override @@ -88,7 +88,7 @@ class PhotoRepositoryImpl extends PhotoRepository { } return Ok(response); } catch (_) { - return Err( + return const Err( ClientException('Cannot retrieve all photos from favorites.'), ); } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart index 769ae81d..ef8a0ec9 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart @@ -33,7 +33,7 @@ class AddPhotoToFavorites extends AsyncUseCase> { @override FutureOr onStart(Photo? params) { if (params == null) { - throw ClientException('Photo cannot be null'); + throw const ClientException('Photo cannot be null'); } } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart index 7ff464ce..f0dcfa5c 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart @@ -30,7 +30,7 @@ class CheckIfPhotoIsInFavorites extends AsyncUseCase { @override FutureOr onStart(int? params) { if (params == null) { - throw ClientException('id cannot be null'); + throw const ClientException('id cannot be null'); } } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart index 36076c70..79a06b8a 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart @@ -33,7 +33,7 @@ class DisplayPhoto extends AsyncUseCase { @override FutureOr onStart(int? params) { if (params == null) { - throw ClientException('id cannot be null'); + throw const ClientException('id cannot be null'); } } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart index 8badf689..358e86a2 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart @@ -39,7 +39,7 @@ class OpenAlbum extends AsyncUseCase> { @override FutureOr onStart(QueryParameters? params) { if (params == null) { - throw ClientException('params cannot be null'); + throw const ClientException('params cannot be null'); } } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart index 737c59a1..e73206b3 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart @@ -33,7 +33,7 @@ class RemovePhotoFromFavorites extends AsyncUseCase> { @override FutureOr onStart(int? params) { if (params == null) { - throw ClientException('id cannot be null'); + throw const ClientException('id cannot be null'); } } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart index 0fc6a757..e88f8a12 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart @@ -37,7 +37,7 @@ class RetrieveAllAlbums extends AsyncUseCase> { @override FutureOr onStart(QueryParameters? params) { if (params == null) { - throw ClientException('params cannot be null'); + throw const ClientException('params cannot be null'); } } } diff --git a/packages/wyatt_architecture/lib/src/core/exceptions/exceptions.dart b/packages/wyatt_architecture/lib/src/core/exceptions/exceptions.dart index 3fb15944..e1fa8e9a 100644 --- a/packages/wyatt_architecture/lib/src/core/exceptions/exceptions.dart +++ b/packages/wyatt_architecture/lib/src/core/exceptions/exceptions.dart @@ -16,8 +16,13 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +/// {@template app_exception} +/// [AppException] is a base class for all exceptions in the wyatt architecture. +/// {@endtemplate} abstract class AppException implements Exception { - AppException([this.message]); + /// {@macro app_exception} + const AppException([this.message]); + final String? message; @override @@ -30,10 +35,20 @@ abstract class AppException implements Exception { } } +/// {@template client_exception} +/// [ClientException] is a base class for all client exceptions in the wyatt +/// architecture. +/// {@endtemplate} class ClientException extends AppException { - ClientException([super.message]); + /// {@macro client_exception} + const ClientException([super.message]); } +/// {@template server_exception} +/// [ServerException] is a base class for all server exceptions in the wyatt +/// architecture. +/// {@endtemplate} class ServerException extends AppException { - ServerException([super.message]); + /// {@macro server_exception} + const ServerException([super.message]); } diff --git a/packages/wyatt_architecture/lib/src/domain/data_sources/base_data_source.dart b/packages/wyatt_architecture/lib/src/domain/data_sources/base_data_source.dart index 5dc243db..f5002603 100644 --- a/packages/wyatt_architecture/lib/src/domain/data_sources/base_data_source.dart +++ b/packages/wyatt_architecture/lib/src/domain/data_sources/base_data_source.dart @@ -14,6 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template base_data_source} +/// [BaseDataSource] is a base class for all data sources in the wyatt +/// architecture. +/// {@endtemplate} abstract class BaseDataSource { + /// {@macro base_data_source} const BaseDataSource(); } diff --git a/packages/wyatt_architecture/lib/src/domain/data_sources/local/base_local_data_source.dart b/packages/wyatt_architecture/lib/src/domain/data_sources/local/base_local_data_source.dart index 1d7c134c..b091a13f 100644 --- a/packages/wyatt_architecture/lib/src/domain/data_sources/local/base_local_data_source.dart +++ b/packages/wyatt_architecture/lib/src/domain/data_sources/local/base_local_data_source.dart @@ -16,6 +16,11 @@ import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; +/// {@template base_local_data_source} +/// [BaseLocalDataSource] is a base class for all local data sources in the +/// wyatt architecture. +/// {@endtemplate} abstract class BaseLocalDataSource extends BaseDataSource { + /// {@macro base_local_data_source} const BaseLocalDataSource(); } diff --git a/packages/wyatt_architecture/lib/src/domain/data_sources/remote/base_remote_data_source.dart b/packages/wyatt_architecture/lib/src/domain/data_sources/remote/base_remote_data_source.dart index a4a72999..8ed880c4 100644 --- a/packages/wyatt_architecture/lib/src/domain/data_sources/remote/base_remote_data_source.dart +++ b/packages/wyatt_architecture/lib/src/domain/data_sources/remote/base_remote_data_source.dart @@ -16,6 +16,11 @@ import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; +/// {@template base_remote_data_source} +/// [BaseRemoteDataSource] is a base class for all remote data sources in the +/// wyatt architecture. +/// {@endtemplate} abstract class BaseRemoteDataSource extends BaseDataSource { + /// {@macro base_remote_data_source} const BaseRemoteDataSource(); } diff --git a/packages/wyatt_architecture/lib/src/domain/entities/entity.dart b/packages/wyatt_architecture/lib/src/domain/entities/entity.dart index fd988950..41a8ca17 100644 --- a/packages/wyatt_architecture/lib/src/domain/entities/entity.dart +++ b/packages/wyatt_architecture/lib/src/domain/entities/entity.dart @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template entity} +/// [Entity] is a base class for all entities in the domain layer. +/// {@endtemplate} abstract class Entity { + /// {@macro entity} const Entity(); } diff --git a/packages/wyatt_architecture/lib/src/domain/repositories/base_repository.dart b/packages/wyatt_architecture/lib/src/domain/repositories/base_repository.dart index 4a08a0db..a7e26b12 100644 --- a/packages/wyatt_architecture/lib/src/domain/repositories/base_repository.dart +++ b/packages/wyatt_architecture/lib/src/domain/repositories/base_repository.dart @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template base_repository} +/// [BaseRepository] is a base class for all repositories in the domain layer. +/// {@endtemplate} abstract class BaseRepository { + /// {@macro base_repository} const BaseRepository(); } diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/no_param.dart b/packages/wyatt_architecture/lib/src/domain/usecases/no_param.dart index 7452af67..4509bd59 100644 --- a/packages/wyatt_architecture/lib/src/domain/usecases/no_param.dart +++ b/packages/wyatt_architecture/lib/src/domain/usecases/no_param.dart @@ -16,6 +16,11 @@ import 'package:wyatt_architecture/src/domain/entities/entity.dart'; +/// {@template no_param} +/// [NoParam] is a class that is used when a use case does not require any +/// parameters. +/// {@endtemplate} class NoParam extends Entity { + /// {@macro no_param} const NoParam(); } diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart b/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart index 370546fe..a1925577 100644 --- a/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart +++ b/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart @@ -21,16 +21,17 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; /// Usecase observers mixin Observer { /// Called before usecase is runned. - /// Usefull to check the preconditions + /// Useful to check the preconditions FutureOr onStart(Parameters? params) {} /// Called when error occures during main scenario - /// Usefull to run alternative scenario + /// Useful to run alternative scenario FutureOr onError(AppException? error) {} } /// Specific observer for classic usecase mixin AsyncObserver { + /// Called when usecase is completed FutureOr onComplete(ReturnType? data) {} } @@ -39,6 +40,6 @@ mixin StreamObserver { /// Replaces the data event handler of this subscription. void onDone() {} - /// Replaces the done event handler of this subscription. + /// Replaces the done event handler of this subscription. void onData(ReturnType? data) {} } diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart b/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart index c406535d..75c4c905 100644 --- a/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart +++ b/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart @@ -23,8 +23,13 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart'; typedef FutureOrResult = FutureOr>; typedef StreamResult = Stream>; -/// Abstract class of a use case +/// {@template base_usecase} +/// Abstract class of any use case. +/// {@endtemplate} abstract class BaseUseCase { + /// {@macro base_usecase} + const BaseUseCase(); + /// Run use case scenarios ReturnType call(Parameters parameters); @@ -33,11 +38,16 @@ abstract class BaseUseCase { ReturnType execute(Parameters params); } +/// {@template usecase} /// Abstract class of a use case that deals specifically /// with the response and its state. +/// {@endtemplate} abstract class UseCase extends BaseUseCase> with Observer { + /// {@macro usecase} + const UseCase(); + FutureOr _onSuccess(ReturnType data); /// Supports the result of the main scenario and integrates @@ -59,17 +69,27 @@ abstract class UseCase } } -/// Abtstract classic usecase. +/// {@template async_usecase} +/// Abtstract classic usecase bases on futures +/// {@endtemplate} abstract class AsyncUseCase extends UseCase with AsyncObserver { + /// {@macro async_usecase} + const AsyncUseCase(); + @override FutureOr _onSuccess(ReturnType data) => onComplete(data); } +/// {@template stream_usecase} /// Abstract specific usecase bases on streams +/// {@endtemplate} abstract class StreamUseCase extends UseCase> with StreamObserver { + /// {@macro stream_usecase} + const StreamUseCase(); + @override FutureOr _onSuccess(Stream data) { data.listen( diff --git a/packages/wyatt_architecture/lib/wyatt_architecture.dart b/packages/wyatt_architecture/lib/wyatt_architecture.dart index 54c20e0d..f07613aa 100644 --- a/packages/wyatt_architecture/lib/wyatt_architecture.dart +++ b/packages/wyatt_architecture/lib/wyatt_architecture.dart @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// Architecture +/// Wyatt Architecture for Flutter library wyatt_architecture; export 'src/src.dart'; diff --git a/packages/wyatt_architecture/pubspec.yaml b/packages/wyatt_architecture/pubspec.yaml index cac59f5f..e447fa29 100644 --- a/packages/wyatt_architecture/pubspec.yaml +++ b/packages/wyatt_architecture/pubspec.yaml @@ -1,27 +1,35 @@ +# Copyright (C) 2023 WYATT GROUP +# Please see the AUTHORS file for details. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + name: wyatt_architecture -description: A new Wyatt package +description: Wyatt Architecture contains useful classes to help you to create a clean architecture following the Wyatt Architecture principles. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_architecture version: 0.1.0+1 publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: - sdk: '>=2.17.0 <3.0.0' + sdk: ">=2.17.0 <3.0.0" dependencies: - - flutter: - sdk: flutter - wyatt_type_utils: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub version: ^0.0.4 dev_dependencies: - - flutter_test: - sdk: flutter - wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub - version: ^2.4.1 \ No newline at end of file + version: ^2.4.1 diff --git a/packages/wyatt_authentication_bloc/.gitignore b/packages/wyatt_authentication_bloc/.gitignore deleted file mode 100644 index 23d156c3..00000000 --- a/packages/wyatt_authentication_bloc/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.packages -build/ -.flutter-plugins* -coverage/ \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/.gitignore b/packages/wyatt_authentication_bloc/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_authentication_bloc/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/.pubignore b/packages/wyatt_authentication_bloc/.pubignore deleted file mode 100644 index 11610c5a..00000000 --- a/packages/wyatt_authentication_bloc/.pubignore +++ /dev/null @@ -1,2 +0,0 @@ -firebase_options.dart -.vscode \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/.pubignore b/packages/wyatt_authentication_bloc/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_authentication_bloc/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/AUTHORS b/packages/wyatt_authentication_bloc/AUTHORS deleted file mode 100644 index b6d7d765..00000000 --- a/packages/wyatt_authentication_bloc/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/AUTHORS b/packages/wyatt_authentication_bloc/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_authentication_bloc/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/LICENSE b/packages/wyatt_authentication_bloc/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_authentication_bloc/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/LICENSE b/packages/wyatt_authentication_bloc/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_authentication_bloc/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/README.md b/packages/wyatt_authentication_bloc/README.md index 755c77e0..9d58adfb 100644 --- a/packages/wyatt_authentication_bloc/README.md +++ b/packages/wyatt_authentication_bloc/README.md @@ -1,5 +1,5 @@ -# Flutter - Authentication BLoC +# Authentication BLoC

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Flutter

@@ -29,37 +27,195 @@ Authentication Bloc for Flutter. ## Features -- Wyatt Architecture -- Entities: - - Account : AccountModel -> Contains account information from provider - - AccountWrapper : AccountWrapperModel -> Contains account and extra data. -- Data Sources: - - Local: - - Cached Authentication Data : AuthenticationCacheDataSourceImpl -> Provides a cache implementation - - Remote: - - Remote Authentication Data : AuthenticationFirebaseDataSourceImpl -> Provides a proxy to FirebaseAuth -- Repositories: - - AuthenticationRepository : AuthenticationRepositoryImpl -> Provides all authentication methods -- Features: - - Authentication: - - AuthenticationBuilder : widget to build reactive view from authentication state - - AuthenticationCubit : tracks every auth changes, have sign out capability. - - SignUp: - - SignUpCubit: implementation of a FormDataCubit from `wyatt_form_bloc` for the sign up - - SignIn: - - SignUpCubit: implementation of a FormDataCubit from `wyatt_form_bloc` for the sign in -- Consistent - * Every class have same naming convention -- Tested +* 🧐 Wyatt Architecture +* 🧱 Entities + - Account -> Contains account information from provider. + - Session -> Contains account and associated data retrieved from an external source. + - AuthenticationChangeEvent -> Describes an event in authentication change (sign in, sign up, sign out, etc...) + - SessionWrapper -> Contains latest authentication change event and session. +* 🔑 Powerful and secured authentication repository +* 🔥 Multiple data sources + - Mock + - Firebase +* 🧊 Cubits, why make it complicated when you can make it simple? + - Goes to the essential. +* 📐 Consistent + - Every class have same naming convention +* 🧪 Tested +* 📚 Documented: [available here](./doc/api/index.md) ## Getting started -Simply add `wyatt_authentication_bloc` in `pubspec.yaml`, then +Simply add `wyatt_authentication_bloc` in `pubspec.yaml` , then ```dart import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; ``` -## Usage +### Data source -// TODO \ No newline at end of file +The first step is to provide a data source. + +```dart +getIt.registerLazySingleton>( + () => AuthenticationFirebaseDataSourceImpl( + firebaseAuth: FirebaseAuth.instance, + googleSignIn: + GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), +); +``` + +> Here we use GetIt (see example project) + +### Repository + +Then you can configure your repository. + +```dart +final AuthenticationRepository authenticationRepository = AuthenticationRepositoryImpl( + authenticationRemoteDataSource: + getIt>(), + customPasswordValidator: const CustomPassword.pure(), + extraSignUpInputs: [ + FormInput( + AuthFormField.confirmPassword, + const ConfirmedPassword.pure(), + metadata: const FormInputMetadata(export: false), + ), + ], +); +``` + +> Here we pass some extra inputs for the sign up, and a custom password validator. + +### Cubits + +It is necessary to implement each cubit. Don't panic, most of the work is already done 😊 you just have to customize the logic of these. + +In each of these cubits it is necessary to overload the various callbacks. + +> Here the associated data `Data` is a `int` + +#### Authentication + +In the authentication are managed, the refresh, the deletion of account or the disconnection. + +```dart +class ExampleAuthenticationCubit extends AuthenticationCubit { + ExampleAuthenticationCubit({required super.authenticationRepository}); + + @override + FutureOrResult onReauthenticate(Result result) async { + // TODO + } + + @override + FutureOrResult onRefresh(Result result) { + // TODO + } + + @override + FutureOrResult onSignInFromCache(SessionWrapper wrapper) { + // TODO + } + + @override + FutureOrResult onSignOut() { + // TODO + } + + @override + FutureOrResult onDelete() { + // TODO + } +} +``` + +#### Sign Up + +```dart +class ExampleSignUpCubit extends SignUpCubit { + ExampleSignUpCubit({ + required super.authenticationRepository, + }); + + @override + FutureOrResult onSignUpWithEmailAndPassword(Result result, WyattForm form) async { + // TODO + } +} + +``` + +#### Sign In + +```dart +class ExampleSignInCubit extends SignInCubit { + ExampleSignInCubit({ + required super.authenticationRepository, + }); + + @override + FutureOrResult onSignInWithEmailAndPassword(Result result, WyattForm form) { + // TODO + } + + @override + FutureOrResult onSignInAnonymously(Result result, WyattForm form) { + // TODO + } + + @override + FutureOrResult onSignInWithGoogle(Result result, WyattForm form) { + // TODO + } +} +``` + +After setting up all these cubits you can provide them in the application. And that's it! + +```dart +BlocProvider>( + create: (_) => ExampleSignUpCubit( + authenticationRepository: authenticationRepository, + ), +), +BlocProvider>( + create: (_) => ExampleSignInCubit( + authenticationRepository: authenticationRepository, + ), +), +``` + +### Widgets + +Widgets are provided to make your life easier. Starting with the `AuthenticationBuilder` which allows you to build according to the authentication state. + +```dart +AuthenticationBuilder( + authenticated: (context, sessionWrapper) => Text( + 'Logged as ${sessionWrapper.session?.account.email} | GeneratedId is ${sessionWrapper.session?.data}'), + unauthenticated: (context) => + const Text('Not logged (unauthenticated)'), + unknown: (context) => const Text('Not logged (unknown)'), +), +``` + +A `BuildContext` extension is also available to access certain attributes more quickly. + +```dart +Text('Home | ${context.account, int>()?.email}'), +``` + +Listeners are used to listen to the status of the sign in and sign up forms. + +```dart +return SignInListener( + onError: (context, status, errorMessage) => ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar(content: Text(errorMessage ?? 'Sign In Failure')), + ), + child: ... +); +``` diff --git a/packages/wyatt_authentication_bloc/docs.sh b/packages/wyatt_authentication_bloc/docs.sh new file mode 100755 index 00000000..1b8931fc --- /dev/null +++ b/packages/wyatt_authentication_bloc/docs.sh @@ -0,0 +1,17 @@ +sed -i -e "s/export 'package:firebase_auth\/firebase_auth.dart';/\/\/export 'package:firebase_auth\/firebase_auth.dart';/g" lib/wyatt_authentication_bloc.dart +sed -i -e "s/export 'package:google_sign_in\/google_sign_in.dart';/\/\/export 'package:google_sign_in\/google_sign_in.dart';/g" lib/wyatt_authentication_bloc.dart + +dart pub global activate dartdoc +dart pub global run dartdoc --format md \ + --exclude package:firebase_auth,package:google_sign_in, \ + dart:async,dart:collection,dart:convert,dart:core,dart:developer, \ + dart:io,dart:isolate,dart:math,dart:typed_data,dart:ui,dart:ffi, \ + dart:html,dart:js,dart:js_util \ + --no-auto-include-dependencies \ + --no-validate-links \ + --show-progress \ + +sed -i -e "s/\/\/export 'package:firebase_auth\/firebase_auth.dart';/export 'package:firebase_auth\/firebase_auth.dart';/g" lib/wyatt_authentication_bloc.dart +sed -i -e "s/\/\/export 'package:google_sign_in\/google_sign_in.dart';/export 'package:google_sign_in\/google_sign_in.dart';/g" lib/wyatt_authentication_bloc.dart + +rm lib/wyatt_authentication_bloc.dart-e \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example/.firebaserc b/packages/wyatt_authentication_bloc/example/.firebaserc new file mode 100644 index 00000000..54e8fe84 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "tchat-beta" + } +} diff --git a/packages/wyatt_authentication_bloc/example/.gitignore b/packages/wyatt_authentication_bloc/example/.gitignore index 891ead31..6df3a32a 100644 --- a/packages/wyatt_authentication_bloc/example/.gitignore +++ b/packages/wyatt_authentication_bloc/example/.gitignore @@ -22,7 +22,6 @@ migrate_working_dir/ #.vscode/ # Flutter/Dart/Pub related -**/doc/api/ **/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins diff --git a/packages/wyatt_authentication_bloc/example/README.md b/packages/wyatt_authentication_bloc/example/README.md index 139e82ee..df389404 100644 --- a/packages/wyatt_authentication_bloc/example/README.md +++ b/packages/wyatt_authentication_bloc/example/README.md @@ -1,16 +1,6 @@ # example_router -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +```sh +firebase emulators:start --only auth +flutter run --target lib/main_development.dart --dart-define="dev_mode=emulator" +``` diff --git a/packages/wyatt_authentication_bloc/example/firebase.json b/packages/wyatt_authentication_bloc/example/firebase.json new file mode 100644 index 00000000..c8738c2c --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/firebase.json @@ -0,0 +1,14 @@ +{ + "emulators": { + "auth": { + "port": 9099 + }, + "firestore": { + "port": 8080 + }, + "ui": { + "enabled": true + }, + "singleProjectMode": true + } +} diff --git a/packages/wyatt_authentication_bloc/example/ios/Podfile.lock b/packages/wyatt_authentication_bloc/example/ios/Podfile.lock index bc6894a5..4e5cbe34 100644 --- a/packages/wyatt_authentication_bloc/example/ios/Podfile.lock +++ b/packages/wyatt_authentication_bloc/example/ios/Podfile.lock @@ -10,11 +10,11 @@ PODS: - FirebaseAuth (~> 10.3.0) - Firebase/CoreOnly (10.3.0): - FirebaseCore (= 10.3.0) - - firebase_auth (4.2.0): + - firebase_auth (4.2.9): - Firebase/Auth (= 10.3.0) - firebase_core - Flutter - - firebase_core (2.4.0): + - firebase_core (2.7.0): - Firebase/CoreOnly (= 10.3.0) - Flutter - FirebaseAuth (10.3.0): @@ -29,6 +29,8 @@ PODS: - FirebaseCoreInternal (10.3.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - Flutter (1.0.0) + - flutter_secure_storage (6.0.0): + - Flutter - google_sign_in_ios (0.0.1): - Flutter - GoogleSignIn (~> 6.2) @@ -61,6 +63,7 @@ DEPENDENCIES: - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - Flutter (from `Flutter`) + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) SPEC REPOS: @@ -83,19 +86,22 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" Flutter: :path: Flutter + flutter_secure_storage: + :path: ".symlinks/plugins/flutter_secure_storage/ios" google_sign_in_ios: :path: ".symlinks/plugins/google_sign_in_ios/ios" SPEC CHECKSUMS: AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add Firebase: f92fc551ead69c94168d36c2b26188263860acd9 - firebase_auth: 579a0dc15451491cc83fccaa5102296635f24938 - firebase_core: 6f2f753e316765799d88568232ed59e300ff53db + firebase_auth: 4e8c693e848ed13b263de2d702d55fa82ed04a79 + firebase_core: 128d8c43c3a453a4a67463314fc3761bedff860b FirebaseAuth: 0e415d29d846c1dce2fb641e46f35e9888d9bec6 FirebaseCore: 988754646ab3bd4bdcb740f1bfe26b9f6c0d5f2a FirebaseCoreInternal: 29b76f784d607df8b2a1259d73c3f04f1210137b Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c + flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be + google_sign_in_ios: 1256ff9d941db546373826966720b0c24804bcdd GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95 GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd diff --git a/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj index 11d0d0ad..eda3ed8b 100644 --- a/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,12 +3,13 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 44F5B6790A35D9BA26574F6B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */; }; 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0A061B2E527F311149C3581 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -46,6 +47,7 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B0A061B2E527F311149C3581 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -91,6 +93,7 @@ 97C146EF1CF9000F007C117D /* Products */, 66B357379C2757D2844F12BB /* Pods */, BC1E25CE0DADDF7B7201CCF8 /* Frameworks */, + F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -192,6 +195,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 44F5B6790A35D9BA26574F6B /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -200,6 +204,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -236,6 +241,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist b/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist new file mode 100644 index 00000000..ac60a458 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,38 @@ + + + + + CLIENT_ID + 136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9 + ANDROID_CLIENT_ID + 136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com + API_KEY + AIzaSyCDbbhjbFrQwLXuIANdJzjkDk8uOETnn7w + GCM_SENDER_ID + 136771801992 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.exampleRouter + PROJECT_ID + tchat-beta + STORAGE_BUCKET + tchat-beta.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:136771801992:ios:bcdca68d2b7d227097203d + DATABASE_URL + https://tchat-beta.firebaseio.com + + \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example/ios/firebase_app_id_file.json b/packages/wyatt_authentication_bloc/example/ios/firebase_app_id_file.json index 2a145385..17445d1d 100644 --- a/packages/wyatt_authentication_bloc/example/ios/firebase_app_id_file.json +++ b/packages/wyatt_authentication_bloc/example/ios/firebase_app_id_file.json @@ -1,7 +1,7 @@ { "file_generated_by": "FlutterFire CLI", "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", - "GOOGLE_APP_ID": "1:405351917235:ios:869f0ad8ace08db899f2c6", - "FIREBASE_PROJECT_ID": "meerabel-dev", - "GCM_SENDER_ID": "405351917235" + "GOOGLE_APP_ID": "1:136771801992:ios:bcdca68d2b7d227097203d", + "FIREBASE_PROJECT_ID": "tchat-beta", + "GCM_SENDER_ID": "136771801992" } \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart b/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart index 0f64001a..948e01fd 100644 --- a/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart +++ b/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -18,8 +18,6 @@ import 'dart:async'; import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/utils/app_bloc_observer.dart'; -import 'package:example_router/firebase_options.dart'; -import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -69,11 +67,6 @@ Future bootstrap(FutureOr Function() builder) async { debugPrint(details.toString()); }; - if (MockSettings.isDisable()) { - await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, - ); - } await GetItInitializer.init(); runApp(await builder()); diff --git a/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart b/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart index d1cb33ab..2961e7cb 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart +++ b/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,48 +14,83 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/bootstrap.dart'; +import 'dart:async'; + +import 'package:example_router/core/enums/dev_mode.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/firebase_options.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:get_it/get_it.dart'; +import 'package:google_sign_in/google_sign_in.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; -import 'package:wyatt_type_utils/wyatt_type_utils.dart'; final getIt = GetIt.I; +/// Service and Data Source locator abstract class GetItInitializer { - static Future init() async { + static FutureOr _initCommon() async { + // Initialize common sources/services + getIt.registerLazySingleton>( + () => AuthenticationSessionDataSourceImpl(), + ); + } + + static FutureOr _initEmulator() async { + // Initialize emulator sources/services + final firebaseAuth = FirebaseAuth.instance; + await firebaseAuth.useAuthEmulator('localhost', 9099); getIt - ..registerLazySingleton( - MockSettings.isEnable() - ? () => AuthenticationMockDataSourceImpl(registeredAccounts: [ - Pair( - AccountModel( - uid: '1', - emailVerified: true, - isAnonymous: false, - providerId: 'wyatt', - email: 'toto@test.fr', - ), - 'toto1234', - ), - Pair( - AccountModel( - uid: '2', - emailVerified: false, - isAnonymous: false, - providerId: 'wyatt', - email: 'tata@test.fr', - ), - 'tata1234', - ), - ]) - : () => AuthenticationFirebaseDataSourceImpl( - googleSignIn: GoogleSignIn( - clientId: DefaultFirebaseOptions.ios.iosClientId)), + ..registerLazySingleton>( + () => AuthenticationFirebaseDataSourceImpl( + firebaseAuth: firebaseAuth, + googleSignIn: + GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), ) ..registerLazySingleton>( - () => AuthenticationCacheDataSourceImpl(), + () => AuthenticationFirebaseCacheDataSourceImpl( + firebaseAuth: firebaseAuth, + ), ); + } + + static FutureOr _initFirebase() async { + // Initialize firebase sources/services. + getIt + ..registerLazySingleton>( + () => AuthenticationFirebaseDataSourceImpl( + firebaseAuth: FirebaseAuth.instance, + googleSignIn: + GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), + ) + ..registerLazySingleton>( + () => AuthenticationFirebaseCacheDataSourceImpl( + firebaseAuth: FirebaseAuth.instance, + ), + ); + } + + static FutureOr _initRest() async { + // Initialize rest api sources/services + } + + static FutureOr init() async { + await _initCommon(); + final flavor = Flavor.get(); + + if (flavor.devMode == DevMode.rest) { + await _initRest(); + } else if (flavor.devMode == DevMode.emulator) { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await _initEmulator(); + } else { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await _initFirebase(); + } await getIt.allReady(); } diff --git a/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart b/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart new file mode 100644 index 00000000..5c99b7f8 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart @@ -0,0 +1,44 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +enum DevMode { + /// Mocked values + mock, + + /// Real values from REST API + rest, + + /// Emulated values with Firebase Emulator + emulator, + + /// Real values from Firebase + real; + + @override + String toString() => name; + + /// Tries to parse String and returns mode. Fallback is returned if there + /// is an error during parsing. + static DevMode fromString(String? mode, {DevMode fallback = DevMode.mock}) { + for (final m in values) { + if (m.name == mode) { + return m; + } + } + + return fallback; + } +} diff --git a/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart b/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart new file mode 100644 index 00000000..9fef201a --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart @@ -0,0 +1,72 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:example_router/core/enums/dev_mode.dart'; +import 'package:flutter/material.dart'; + +abstract class Flavor { + Flavor._({ + this.banner, + this.bannerColor = Colors.red, + this.devMode, + }) { + _instance = this; + } + + static Flavor? _instance; + + final String? banner; + final Color bannerColor; + final DevMode? devMode; + + /// Returns [Flavor] instance. + static Flavor get() { + if (_instance == null) { + throw Exception('Flavor not initialized!'); + } + + return _instance!; + } + + @override + String toString() => runtimeType.toString().replaceAll('Flavor', ''); +} + +class DevelopmentFlavor extends Flavor { + factory DevelopmentFlavor() { + const modeString = String.fromEnvironment('dev_mode', defaultValue: 'mock'); + final mode = DevMode.fromString(modeString); + + return DevelopmentFlavor._(devMode: mode); + } + DevelopmentFlavor._({ + required super.devMode, + }) : super._( + banner: 'Dev', + ); +} + +class StagingFlavor extends Flavor { + StagingFlavor() + : super._( + banner: 'Staging', + bannerColor: Colors.green, + ); +} + +class ProductionFlavor extends Flavor { + ProductionFlavor() : super._(); +} diff --git a/packages/wyatt_authentication_bloc/example/lib/core/routes/router.dart b/packages/wyatt_authentication_bloc/example/lib/core/routes/router.dart index 657d3917..f38047f3 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/routes/router.dart +++ b/packages/wyatt_authentication_bloc/example/lib/core/routes/router.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart'; +import 'package:example_router/presentation/features/authentication/sign_in/sign_in_page.dart'; +import 'package:example_router/presentation/features/authentication/sign_up/sign_up_page.dart'; +import 'package:example_router/presentation/features/edit_account/edit_account_page.dart'; import 'package:example_router/presentation/features/home/home_page.dart'; -import 'package:example_router/presentation/features/sign_in/sign_in_page.dart'; -import 'package:example_router/presentation/features/sign_up/sign_up_page.dart'; import 'package:example_router/presentation/features/sub/sub_page.dart'; import 'package:example_router/presentation/features/welcome/welcome_page.dart'; import 'package:flutter/cupertino.dart'; @@ -66,31 +66,32 @@ class AppRouter { ), ), GoRoute( - path: '/home', - name: HomePage.pageName, - pageBuilder: (context, state) => defaultTransition( - context, - state, - const HomePage(), - ), - ), - GoRoute( - path: '/home/sub', - name: SubPage.pageName, - pageBuilder: (context, state) => defaultTransition( - context, - state, - const SubPage(), - ), - ), - GoRoute( - path: '/home/edit', - name: EditProfilePage.pageName, - pageBuilder: (context, state) => defaultTransition( - context, - state, - const EditProfilePage(), - ), - ), + path: '/home', + name: HomePage.pageName, + pageBuilder: (context, state) => defaultTransition( + context, + state, + const HomePage(), + ), + routes: [ + GoRoute( + path: 'sub', + name: SubPage.pageName, + pageBuilder: (context, state) => defaultTransition( + context, + state, + const SubPage(), + ), + ), + GoRoute( + path: 'edit_account', + name: EditAccountPage.pageName, + pageBuilder: (context, state) => defaultTransition( + context, + state, + const EditAccountPage(), + ), + ), + ]), ]; } diff --git a/packages/wyatt_authentication_bloc/example/lib/core/utils/app_bloc_observer.dart b/packages/wyatt_authentication_bloc/example/lib/core/utils/app_bloc_observer.dart index 1a25acfd..abc209cb 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/utils/app_bloc_observer.dart +++ b/packages/wyatt_authentication_bloc/example/lib/core/utils/app_bloc_observer.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/example/lib/core/utils/custom_password.dart b/packages/wyatt_authentication_bloc/example/lib/core/utils/custom_password.dart index d80b6d3e..a7e1c7c8 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/utils/custom_password.dart +++ b/packages/wyatt_authentication_bloc/example/lib/core/utils/custom_password.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart b/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart index 10987933..0725ddb4 100644 --- a/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart +++ b/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart @@ -24,10 +24,7 @@ class DefaultFirebaseOptions { } switch (defaultTargetPlatform) { case TargetPlatform.android: - throw UnsupportedError( - 'DefaultFirebaseOptions have not been configured for android - ' - 'you can reconfigure this by running the FlutterFire CLI again.', - ); + return android; case TargetPlatform.iOS: return ios; case TargetPlatform.macOS: @@ -52,16 +49,26 @@ class DefaultFirebaseOptions { } } + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk', + appId: '1:136771801992:android:ac3cfeb99fb0763e97203d', + messagingSenderId: '136771801992', + projectId: 'tchat-beta', + databaseURL: 'https://tchat-beta.firebaseio.com', + storageBucket: 'tchat-beta.appspot.com', + ); + static const FirebaseOptions ios = FirebaseOptions( - apiKey: 'AIzaSyDDmtf0KN7Xw12_pqUsxoBfAxMuvCMmMmk', - appId: '1:405351917235:ios:869f0ad8ace08db899f2c6', - messagingSenderId: '405351917235', - projectId: 'meerabel-dev', - storageBucket: 'meerabel-dev.appspot.com', + apiKey: 'AIzaSyCDbbhjbFrQwLXuIANdJzjkDk8uOETnn7w', + appId: '1:136771801992:ios:bcdca68d2b7d227097203d', + messagingSenderId: '136771801992', + projectId: 'tchat-beta', + databaseURL: 'https://tchat-beta.firebaseio.com', + storageBucket: 'tchat-beta.appspot.com', androidClientId: - '405351917235-4g1dh3475tq6t1sa2qoh7ol60nf4ta05.apps.googleusercontent.com', + '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com', iosClientId: - '405351917235-2jv4ff02kovoim58f8d6d0rsa14apgkj.apps.googleusercontent.com', + '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com', iosBundleId: 'com.example.exampleRouter', ); } diff --git a/packages/wyatt_authentication_bloc/example/lib/main.dart b/packages/wyatt_authentication_bloc/example/lib/main.dart index ddc4cb52..a8d69968 100644 --- a/packages/wyatt_authentication_bloc/example/lib/main.dart +++ b/packages/wyatt_authentication_bloc/example/lib/main.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,9 +15,13 @@ // along with this program. If not, see . import 'package:example_router/bootstrap.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/presentation/features/app/app.dart'; -void main() { - MockSettings.enable(); +void main(List args) { + // Define environment + ProductionFlavor(); + + // Initialize environment and variables bootstrap(App.new); } diff --git a/packages/wyatt_authentication_bloc/example/lib/main_firebase.dart b/packages/wyatt_authentication_bloc/example/lib/main_development.dart similarity index 79% rename from packages/wyatt_authentication_bloc/example/lib/main_firebase.dart rename to packages/wyatt_authentication_bloc/example/lib/main_development.dart index d53f0050..9025e30f 100644 --- a/packages/wyatt_authentication_bloc/example/lib/main_firebase.dart +++ b/packages/wyatt_authentication_bloc/example/lib/main_development.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,9 +15,13 @@ // along with this program. If not, see . import 'package:example_router/bootstrap.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/presentation/features/app/app.dart'; -void main() { - MockSettings.disable(); +void main(List args) { + // Define environment + DevelopmentFlavor(); + + // Initialize environment and variables bootstrap(App.new); } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart index 99d1d999..51b038d9 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,58 +15,32 @@ // along with this program. If not, see . import 'dart:async'; -import 'dart:math'; -import 'package:example_router/core/constants/form_field.dart'; import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/routes/router.dart'; import 'package:example_router/core/utils/custom_password.dart'; -import 'package:example_router/core/utils/forms.dart'; +import 'package:example_router/presentation/features/authentication/authentication_cubit.dart'; +import 'package:example_router/presentation/features/authentication/sign_in/blocs/sign_in_cubit.dart'; +import 'package:example_router/presentation/features/authentication/sign_up/blocs/sign_up_cubit.dart'; +import 'package:example_router/presentation/features/edit_account/blocs/edit_account_cubit.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -import 'package:wyatt_architecture/wyatt_architecture.dart'; - -FutureOrResult onSignUpSuccess( - AuthenticationRepository repo, - Account? account, - WyattForm form, -) async { - const id = -1; - final confirmedPassword = - form.valueOf(AppFormField.confirmedPassword); - - debugPrint( - 'onSignUpSuccess: $account, generatedId: $id, extraFormData: $confirmedPassword'); - return const Ok(id); -} - -FutureOrResult onAccountChanges( - AuthenticationRepository repo, - Account? account, -) async { - final id = Random().nextInt(1000); - final token = - await repo.getIdentityToken().fold((value) => value, (error) => 'null'); - - debugPrint('onAccountChanges: $account, token: $token, generatedId: $id'); - return Ok(id); -} class App extends StatelessWidget { final AuthenticationRepository authenticationRepository = AuthenticationRepositoryImpl( + authenticationRemoteDataSource: + getIt>(), + authenticationSessionDataSource: + getIt>(), authenticationCacheDataSource: getIt>(), - authenticationRemoteDataSource: getIt(), - onSignUpSuccess: onSignUpSuccess, - onAuthChange: onAccountChanges, customPasswordValidator: const CustomPassword.pure(), extraSignUpInputs: [ FormInput( - AppFormField.confirmedPassword, + AuthFormField.confirmPassword, const ConfirmedPassword.pure(), metadata: const FormInputMetadata(export: false), ), @@ -80,7 +54,8 @@ class App extends StatelessWidget { AuthenticationState? previous; final AuthenticationCubit authenticationCubit = - AuthenticationCubit(authenticationRepository: authenticationRepository); + ExampleAuthenticationCubit( + authenticationRepository: authenticationRepository); final GoRouter router = GoRouter( initialLocation: '/', @@ -107,7 +82,7 @@ class App extends StatelessWidget { return '/home'; } } - return null; + return state.name; }, ); @@ -117,9 +92,8 @@ class App extends StatelessWidget { value: authenticationRepository, ), RepositoryProvider( - create: (context) => - FormRepositoryImpl()..registerForm(AppForms.getEditProfileForm()), - ), + create: (context) => FormRepositoryImpl(), + ) ], child: MultiBlocProvider( providers: [ @@ -127,12 +101,17 @@ class App extends StatelessWidget { value: authenticationCubit, ), BlocProvider>( - create: (_) => SignUpCubit( + create: (_) => ExampleSignUpCubit( authenticationRepository: authenticationRepository, ), ), BlocProvider>( - create: (_) => SignInCubit( + create: (_) => ExampleSignInCubit( + authenticationRepository: authenticationRepository, + ), + ), + BlocProvider>( + create: (_) => ExampleEditAccountCubit( authenticationRepository: authenticationRepository, ), ), diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/authentication_cubit.dart similarity index 51% rename from packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/authentication_cubit.dart index abcb673a..04153f31 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/authentication_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,53 +14,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'package:flutter/foundation.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -class AuthenticationCacheDataSourceImpl - extends AuthenticationCacheDataSource { - AuthenticationCacheDataSourceImpl(); - Account? _account; - T? _data; +class ExampleAuthenticationCubit extends AuthenticationCubit { + ExampleAuthenticationCubit({required super.authenticationRepository}); @override - Future storeAccount(Account? account) async { - _account = account; + FutureOrResult onReauthenticate( + Result result) async { + debugPrint('onReauthenticate'); + + return const Ok(1); } @override - Future storeData(T? data) async { - _data = data; + FutureOrResult onRefresh(Result result) { + debugPrint('onRefresh'); + + return const Ok(1); } @override - Future loadAccount() async { - if (_account.isNotNull) { - return _account!; - } - throw ClientException('Cached account is invalid'); + FutureOrResult onSignInFromCache(AuthenticationSession session) { + debugPrint('onSignInFromCache'); + + return const Ok(1); } @override - Future loadData() async { - if (_data.isNotNull) { - return _data!; - } - throw ClientException('Cached data is invalid'); + FutureOrResult onSignOut() { + debugPrint('onSignOut'); + + return const Ok(null); } @override - Future destroy() async { - _data = null; - _account = null; - } + FutureOrResult onDelete() { + debugPrint('onDelete'); - @override - Future> load() async { - if (_account.isNull) { - throw ClientException('Cached account is invalid'); - } - return AccountWrapperModel(_account, _data); + return const Ok(null); } } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/blocs/sign_in_cubit.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/blocs/sign_in_cubit.dart new file mode 100644 index 00000000..0b391624 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/blocs/sign_in_cubit.dart @@ -0,0 +1,51 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/foundation.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class ExampleSignInCubit extends SignInCubit { + ExampleSignInCubit({ + required super.authenticationRepository, + }); + + @override + FutureOrResult onSignInWithEmailAndPassword( + Result result, WyattForm form) { + debugPrint('onSignInWithEmailAndPassword: ${result.ok?.accessToken}'); + + return const Ok(1); + } + + @override + FutureOrResult onSignInAnonymously( + Result result, WyattForm form) { + debugPrint('onSignInAnonymously'); + + return const Ok(1); + } + + @override + FutureOrResult onSignInWithGoogle( + Result result, WyattForm form) { + debugPrint('onSignInWithGoogle'); + + return const Ok(1); + } +} diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/sign_in_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/sign_in_page.dart similarity index 89% rename from packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/sign_in_page.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/sign_in_page.dart index 19dfd0b6..5294fed0 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/sign_in_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/sign_in_page.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/presentation/features/sign_in/widgets/sign_in_form.dart'; +import 'package:example_router/presentation/features/authentication/sign_in/widgets/sign_in_form.dart'; import 'package:flutter/material.dart'; class SignInPage extends StatelessWidget { diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/widgets/sign_in_form.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/widgets/sign_in_form.dart similarity index 88% rename from packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/widgets/sign_in_form.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/widgets/sign_in_form.dart index f0e1dfa9..ebb65583 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_in/widgets/sign_in_form.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_in/widgets/sign_in_form.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -121,21 +121,19 @@ class SignInForm extends StatelessWidget { ..showSnackBar( SnackBar(content: Text(errorMessage ?? 'Sign In Failure')), ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - _EmailInput(), - const SizedBox(height: 8), - _PasswordInput(), - const SizedBox(height: 16), - _SignInButton(), - const SizedBox(height: 16), - _SignInAnonymouslyButton(), - const SizedBox(height: 16), - _SignInWithGoogleButton(), - ], - ), + child: ListView( + shrinkWrap: true, + children: [ + _EmailInput(), + const SizedBox(height: 8), + _PasswordInput(), + const SizedBox(height: 16), + _SignInButton(), + const SizedBox(height: 16), + _SignInAnonymouslyButton(), + const SizedBox(height: 16), + _SignInWithGoogleButton(), + ], ), ); } diff --git a/packages/wyatt_authentication_bloc/example/lib/core/utils/forms.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/blocs/sign_up_cubit.dart similarity index 57% rename from packages/wyatt_authentication_bloc/example/lib/core/utils/forms.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/blocs/sign_up_cubit.dart index abfc6857..93c4509e 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/utils/forms.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/blocs/sign_up_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,19 +14,22 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/core/constants/form_field.dart'; -import 'package:example_router/core/constants/form_name.dart'; -import 'package:example_router/core/utils/custom_password.dart'; +import 'package:flutter/foundation.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -abstract class AppForms { - static WyattForm getEditProfileForm() => WyattFormImpl( - [ - FormInput(AuthFormField.email, const Email.pure()), - FormInput(AuthFormField.password, const CustomPassword.pure()), - FormInput(AppFormField.oldPassword, const CustomPassword.pure()), - ], - name: AppFormName.editProfile, - ); +class ExampleSignUpCubit extends SignUpCubit { + ExampleSignUpCubit({ + required super.authenticationRepository, + }); + + @override + FutureOrResult onSignUpWithEmailAndPassword( + Result result, WyattForm form) async { + debugPrint('onSignUpWithEmailAndPassword'); + + return const Ok(1); + } } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/sign_up_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/sign_up_page.dart similarity index 89% rename from packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/sign_up_page.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/sign_up_page.dart index ff232348..d9963142 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/sign_up_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/sign_up_page.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/presentation/features/sign_up/widgets/sign_up_form.dart'; +import 'package:example_router/presentation/features/authentication/sign_up/widgets/sign_up_form.dart'; import 'package:flutter/material.dart'; class SignUpPage extends StatelessWidget { diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/widgets/sign_up_form.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/widgets/sign_up_form.dart similarity index 84% rename from packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/widgets/sign_up_form.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/widgets/sign_up_form.dart index bb3ebceb..4c13a491 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/authentication/sign_up/widgets/sign_up_form.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/core/constants/form_field.dart'; import 'package:example_router/core/utils/custom_password.dart'; import 'package:flutter/material.dart' hide FormField; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; @@ -51,11 +50,11 @@ class _PasswordInput extends StatelessWidget { cubit.passwordCustomChanged( CustomPassword.dirty(pwd)); cubit.dataChanged( - AppFormField.confirmedPassword, + AuthFormField.confirmPassword, ConfirmedPassword.dirty( password: pwd, value: state.form - .valueOf(AppFormField.confirmedPassword))); + .valueOf(AuthFormField.confirmPassword))); }, obscureText: true, decoration: InputDecoration( @@ -73,7 +72,7 @@ class _ConfirmPasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { return InputBuilder>( - field: AppFormField.confirmedPassword, + field: AuthFormField.confirmPassword, builder: ((context, cubit, state, field, input) { return TextField( onChanged: (pwd) { @@ -106,7 +105,9 @@ class _SignUpButton extends StatelessWidget { return status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( - onPressed: status.isValidated ? () => cubit.submit() : null, + onPressed: status.isValidated + ? () => cubit.signUpWithEmailPassword() + : null, child: const Text('Sign up'), ); }), @@ -126,18 +127,17 @@ class SignUpForm extends StatelessWidget { ..showSnackBar( SnackBar(content: Text(errorMessage ?? 'Sign Up Failure')), ), - child: SingleChildScrollView( - child: Column( - children: [ - _EmailInput(), - const SizedBox(height: 8), - _PasswordInput(), - const SizedBox(height: 8), - _ConfirmPasswordInput(), - const SizedBox(height: 16), - _SignUpButton(), - ], - ), + child: ListView( + shrinkWrap: true, + children: [ + _EmailInput(), + const SizedBox(height: 8), + _PasswordInput(), + const SizedBox(height: 8), + _ConfirmPasswordInput(), + const SizedBox(height: 16), + _SignUpButton(), + ], )); } } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/blocs/edit_account_cubit.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/blocs/edit_account_cubit.dart new file mode 100644 index 00000000..ae964202 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/blocs/edit_account_cubit.dart @@ -0,0 +1,41 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/foundation.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class ExampleEditAccountCubit extends EditAccountCubit { + ExampleEditAccountCubit({required super.authenticationRepository}); + + @override + FutureOrResult onEmailUpdated( + Result result, WyattForm form) async { + debugPrint('onEmailUpdated'); + + return const Ok(1); + } + + @override + FutureOrResult onPasswordUpdated( + Result result, WyattForm form) async { + debugPrint('onPasswordUpdated'); + + return const Ok(1); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/edit_account_page.dart similarity index 53% rename from packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart rename to packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/edit_account_page.dart index 4dae7f6b..11b0f987 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/edit_account_page.dart @@ -1,5 +1,4 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,23 +14,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:example_router/presentation/features/edit_account/widgets/edit_account_form.dart'; +import 'package:flutter/material.dart'; + +class EditAccountPage extends StatelessWidget { + const EditAccountPage({Key? key}) : super(key: key); + + static String pageName = 'EditAccount'; -class AccountWrapperModel extends AccountWrapper { @override - final Account? account; - @override - final T? data; - - AccountWrapperModel(this.account, this.data); - - AccountWrapperModel copyWith({ - Account? account, - T? data, - }) => - AccountWrapperModel( - account ?? this.account, - data ?? this.data, - ); + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Edit Account')), + body: const Padding( + padding: EdgeInsets.all(8), + child: SingleChildScrollView( + child: EditAccountForm(), + ), + ), + ); + } } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/widgets/edit_account_form.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/widgets/edit_account_form.dart new file mode 100644 index 00000000..c80439a9 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_account/widgets/edit_account_form.dart @@ -0,0 +1,151 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:example_router/core/utils/custom_password.dart'; +import 'package:flutter/material.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +class _EmailInput extends StatelessWidget { + @override + Widget build(BuildContext context) { + return InputBuilder>( + field: AuthFormField.email, + builder: ((context, cubit, state, field, input) { + return TextField( + onChanged: (email) => cubit.emailChanged(email), + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'Email', + helperText: '', + errorText: input.validator.invalid ? 'Invalid email' : null, + ), + ); + }), + ); + } +} + +class _PasswordInput extends StatelessWidget { + @override + Widget build(BuildContext context) { + return InputBuilder>( + field: AuthFormField.password, + builder: ((context, cubit, state, field, input) { + return TextField( + onChanged: (pwd) => cubit + .passwordCustomChanged(CustomPassword.dirty(pwd)), + obscureText: true, + decoration: InputDecoration( + labelText: 'Password', + helperText: '', + errorText: input.validator.invalid ? 'Invalid password' : null, + ), + ); + }), + ); + } +} + +class _EditAccountButton extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: status.isValidated + ? () { + cubit.updateEmail(); + cubit.updatePassword(); + } + : null, + child: const Text('Update Account'), + ); + }), + ); + } +} + +class _EditAccountEmailButton extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: status.isValidated + ? () { + cubit.updateEmail(); + } + : null, + child: const Text('Update Account Email'), + ); + }), + ); + } +} + +class _EditAccountPasswordButton extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: status.isValidated + ? () { + cubit.updatePassword(); + } + : null, + child: const Text('Update Account Password'), + ); + }), + ); + } +} + +class EditAccountForm extends StatelessWidget { + const EditAccountForm({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return EditAccountListener( + onError: (context, status, errorMessage) => ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar(content: Text(errorMessage ?? 'Account edition Failure')), + ), + child: ListView( + shrinkWrap: true, + children: [ + _EmailInput(), + const SizedBox(height: 8), + _PasswordInput(), + const SizedBox(height: 16), + _EditAccountButton(), + const SizedBox(height: 16), + _EditAccountEmailButton(), + const SizedBox(height: 16), + _EditAccountPasswordButton(), + ], + ), + ); + } +} diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/blocs/edit_profile_cubit.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/blocs/edit_profile_cubit.dart deleted file mode 100644 index 40063f4c..00000000 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/blocs/edit_profile_cubit.dart +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:example_router/core/constants/form_field.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -import 'package:wyatt_type_utils/wyatt_type_utils.dart'; - -class EditProfileCubit extends FormDataCubitImpl { - final AuthenticationRepository authenticationRepository; - - EditProfileCubit( - super._formRepository, - super._formName, { - required this.authenticationRepository, - }) : super(); - - @override - Future submit() async { - emit( - state.copyWith( - status: FormStatus.submissionInProgress, - ), - ); - // final user = (await authenticationRepository.getAccount()).ok; - - final form = state.form; - final email = form.valueOf(AuthFormField.email); - final oldPassword = form.valueOf(AppFormField.oldPassword); - final newPassword = form.valueOf(AuthFormField.password); - - if (email.isNullOrEmpty || - oldPassword.isNullOrEmpty || - newPassword.isNullOrEmpty) { - emit( - state.copyWith( - errorMessage: 'An error occured while retrieving data from the form.', - status: FormStatus.submissionFailure, - ), - ); - } - - try { - // await authenticationRepository.signInWithEmailAndPassword( - // email: user?.email ?? '', - // password: oldPassword ?? '', - // ); - // await authenticationRepository.reauthenticateWithCredential(); - await authenticationRepository.updateEmail(email: email!); - await authenticationRepository.updatePassword(password: newPassword!); - } on Exception catch (e) { - emit( - state.copyWith( - status: FormStatus.submissionFailure, - errorMessage: e.toString(), - ), - ); - } - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } -} diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/edit_profile_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/edit_profile_page.dart deleted file mode 100644 index a557d338..00000000 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/edit_profile_page.dart +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:example_router/core/constants/form_name.dart'; -import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.dart'; -import 'package:example_router/presentation/features/edit_profile/widgets/edit_profile_form.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -class EditProfilePage extends StatelessWidget { - const EditProfilePage({Key? key}) : super(key: key); - - static String pageName = 'EditProfile'; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Edit Profile')), - body: Padding( - padding: const EdgeInsets.all(8), - child: SingleChildScrollView( - child: BlocProvider( - create: (context) => EditProfileCubit( - context.read(), - AppFormName.editProfile, - authenticationRepository: - context.read>(), - )..dataChanged( - AuthFormField.email, - Email.dirty( - context - .read>() - .state - .accountWrapper - ?.account - ?.email ?? - '', - ), - ), - child: const EditProfileForm(), - ), - ), - ), - ); - } -} diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/widgets/edit_profile_form.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/widgets/edit_profile_form.dart deleted file mode 100644 index 726e51a4..00000000 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/edit_profile/widgets/edit_profile_form.dart +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:example_router/core/constants/form_field.dart'; -import 'package:example_router/core/utils/custom_password.dart'; -import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -class _EmailInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return InputBuilderTextController( - field: AuthFormField.email, - builder: ((context, cubit, state, field, input, controller, extra) { - return TextField( - onChanged: (email) => cubit.dataChanged( - AuthFormField.email, Email.dirty(email)), - keyboardType: TextInputType.emailAddress, - controller: controller, - decoration: InputDecoration( - labelText: 'Email', - helperText: '', - errorText: input.validator.invalid ? 'Invalid email' : null, - ), - ); - }), - ); - } -} - -class _OldPasswordInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return InputBuilder( - field: AppFormField.oldPassword, - builder: ((context, cubit, state, field, input) { - return TextField( - onChanged: (pwd) => cubit.dataChanged( - AppFormField.oldPassword, CustomPassword.dirty(pwd)), - obscureText: true, - decoration: InputDecoration( - labelText: 'Old Password', - helperText: '', - errorText: input.validator.invalid ? 'Invalid password' : null, - ), - ); - }), - ); - } -} - -class _NewPasswordInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return InputBuilder( - field: AuthFormField.password, - builder: ((context, cubit, state, field, input) { - return TextField( - onChanged: (pwd) => cubit.dataChanged( - AuthFormField.password, CustomPassword.dirty(pwd)), - obscureText: true, - decoration: InputDecoration( - labelText: 'New Password', - helperText: '', - errorText: input.validator.invalid ? 'Invalid password' : null, - ), - ); - }), - ); - } -} - -class _EditButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return SubmitBuilder( - builder: ((context, cubit, status) { - return status.isSubmissionInProgress - ? const CircularProgressIndicator() - : ElevatedButton( - onPressed: status.isValidated ? () => cubit.submit() : null, - child: const Text('Edit profile'), - ); - }), - ); - } -} - -class EditProfileForm extends StatelessWidget { - const EditProfileForm({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - if (state.status == FormStatus.submissionFailure) { - ScaffoldMessenger.of(context) - ..hideCurrentSnackBar() - ..showSnackBar( - SnackBar(content: Text(state.errorMessage ?? 'Edit Failure')), - ); - } - }, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - _EmailInput(), - const SizedBox(height: 8), - _OldPasswordInput(), - const SizedBox(height: 8), - _NewPasswordInput(), - const SizedBox(height: 16), - _EditButton(), - ], - ), - ), - ); - } -} diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/home/home_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/home/home_page.dart index a015690b..463ea902 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/home/home_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/home/home_page.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart'; +import 'package:example_router/presentation/features/edit_account/edit_account_page.dart'; import 'package:example_router/presentation/features/sub/sub_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -30,7 +30,7 @@ class HomePage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text('Home'), + title: Text('Home | ${context.watchAccount()?.email}'), actions: [ IconButton( onPressed: () => @@ -40,29 +40,27 @@ class HomePage extends StatelessWidget { ), body: Padding( padding: const EdgeInsets.all(8), - child: SingleChildScrollView( - child: Column( - children: [ - AuthenticationBuilder( - authenticated: (context, accountWrapper) => Text( - 'Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'), - unauthenticated: (context) => - const Text('Not logged (unauthenticated)'), - unknown: (context) => const Text('Not logged (unknown)'), - ), - const SizedBox( - height: 8, - ), - ElevatedButton( - onPressed: () => context.pushNamed(SubPage.pageName), - child: const Text('Go to sub page'), - ), - ElevatedButton( - onPressed: () => context.pushNamed(EditProfilePage.pageName), - child: const Text('Go to edit profile page'), - ), - ], - ), + child: ListView( + children: [ + AuthenticationBuilder( + authenticated: (context, session) => Text( + 'Logged as ${session.account?.email} | GeneratedId is ${session.data}'), + unauthenticated: (context) => + const Text('Not logged (unauthenticated)'), + unknown: (context) => const Text('Not logged (unknown)'), + ), + const SizedBox( + height: 8, + ), + ElevatedButton( + onPressed: () => context.pushNamed(SubPage.pageName), + child: const Text('Go to sub page'), + ), + ElevatedButton( + onPressed: () => context.pushNamed(EditAccountPage.pageName), + child: const Text('Go to edit account page'), + ), + ], ), ), ); diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart index a5c8a6b6..f56df50b 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -35,14 +35,21 @@ class SubPage extends StatelessWidget { icon: const Icon(Icons.logout_rounded)), IconButton( onPressed: () => - context.read>().refresh(), + context.read>().refresh(), icon: const Icon(Icons.refresh)) ], ), - body: const Padding( - padding: EdgeInsets.all(8), - child: SingleChildScrollView( - child: Text('Another page'), + body: Padding( + padding: const EdgeInsets.all(8), + child: ListView( + children: [ + const Text('Another page'), + ElevatedButton( + onPressed: () => + context.read>().delete(), + child: const Text('Delete account'), + ), + ], ), ), ); diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/welcome/welcome_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/welcome/welcome_page.dart index 10d5c0cc..2d2ab4bc 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/welcome/welcome_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/welcome/welcome_page.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:example_router/presentation/features/sign_in/sign_in_page.dart'; -import 'package:example_router/presentation/features/sign_up/sign_up_page.dart'; +import 'package:example_router/presentation/features/authentication/sign_in/sign_in_page.dart'; +import 'package:example_router/presentation/features/authentication/sign_up/sign_up_page.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -30,22 +30,26 @@ class WelcomePage extends StatelessWidget { appBar: AppBar( title: const Text('Welcome'), ), - body: SingleChildScrollView( - child: Column( - children: [ - ElevatedButton( + body: ListView( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( onPressed: () => context.pushNamed(SignUpPage.pageName), child: const Text('Sign Up')), - ElevatedButton( + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( onPressed: () => context.pushNamed(SignInPage.pageName), style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.white), foregroundColor: MaterialStateProperty.all(Colors.blue)), - child: const Text('Sign In')) - ], - ), + child: const Text('Sign In')), + ) + ], ), ); } diff --git a/packages/wyatt_authentication_bloc/example/pubspec.yaml b/packages/wyatt_authentication_bloc/example/pubspec.yaml index 28001220..e1fbdb31 100644 --- a/packages/wyatt_authentication_bloc/example/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/example/pubspec.yaml @@ -33,6 +33,8 @@ dependencies: go_router: ^5.1.5 firebase_core: ^2.1.1 flutter_bloc: ^8.1.1 + firebase_auth: ^4.2.0 + google_sign_in: ^5.4.2 get_it: ^7.2.0 wyatt_authentication_bloc: diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart index 295cfc2f..590e9ae6 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Default authentication form fields name abstract class AuthFormField { + /// Email field: `wyattEmailField` static const email = 'wyattEmailField'; + + /// Password field: `wyattPasswordField` static const password = 'wyattPasswordField'; + + /// Confirm Password field: `wyattConfirmPasswordField` + static const confirmPassword = 'wyattConfirmPasswordField'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart index af623e70..17281b1e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,8 +14,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Default authentication form name abstract class AuthFormName { + /// Sign Up form: `wyattSignUpForm` static const String signUpForm = 'wyattSignUpForm'; + + /// Sign In form: `wyattSignInForm` static const String signInForm = 'wyattSignInForm'; + + /// Password reset form: `wyattPasswordResetForm` static const String passwordResetForm = 'wyattPasswordResetForm'; + + /// Edit account form: `wyattEditAccountForm` + static const String editAccountForm = 'wyattEditAccountForm'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/storage.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/storage.dart new file mode 100644 index 00000000..5211fe72 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/storage.dart @@ -0,0 +1,30 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +/// Default name for storage keys +abstract class AuthStorage { + /// Refresh token, `wyattRefreshToken` + static const String refreshToken = 'wyattRefreshToken'; + + /// Access token, `wyattAccessToken` + static const String accessToken = 'wyattAccessToken'; + + /// User email, `wyattEmail` + static const String email = 'wyattEmail'; + + /// User id, `wyattId` + static const String id = 'wyattId'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/core.dart b/packages/wyatt_authentication_bloc/lib/src/core/core.dart index 2d4165fc..da22baa1 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/core.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/core.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -18,3 +18,5 @@ export 'constants/form_field.dart'; export 'constants/form_name.dart'; export 'enums/enums.dart'; export 'exceptions/exceptions.dart'; +export 'extensions/build_context_extension.dart'; +export 'utils/custom_routine.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart index 11386588..4a96cc46 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,8 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Different authentication status enum AuthenticationStatus { + /// At the application launch. unknown, + + /// When the user is logged authenticated, + + /// When the user is not logged unauthenticated, } diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart index db37d714..de021091 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart index f60c915e..0fb036f7 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,8 +16,11 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; +part 'exceptions_base.dart'; part 'exceptions_firebase.dart'; +part 'exceptions_mock.dart'; +/// Base exception used in Wyatt Authentication abstract class AuthenticationFailureInterface extends AppException implements Exception { AuthenticationFailureInterface(this.code, this.msg); @@ -249,13 +252,9 @@ abstract class SignOutFailureInterface extends AuthenticationFailureInterface { SignOutFailureInterface.fromCode(super.code) : super.fromCode(); } -abstract class GetIdTokenFailureInterface - extends AuthenticationFailureInterface { - GetIdTokenFailureInterface(super.code, super.msg); - - GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode(); -} - +/// {@template reauthenticate_failure} +/// Thrown during the reauthentication process if a failure occurs. +/// {@endtemplate} abstract class ReauthenticateFailureInterface extends AuthenticationFailureInterface { ReauthenticateFailureInterface(super.code, super.msg); @@ -263,6 +262,9 @@ abstract class ReauthenticateFailureInterface ReauthenticateFailureInterface.fromCode(super.code) : super.fromCode(); } +/// {@template update_email_failure} +/// Thrown during the email modification process if a failure occurs. +/// {@endtemplate} abstract class UpdateEmailFailureInterface extends AuthenticationFailureInterface { UpdateEmailFailureInterface(super.code, super.msg); @@ -270,6 +272,9 @@ abstract class UpdateEmailFailureInterface UpdateEmailFailureInterface.fromCode(super.code) : super.fromCode(); } +/// {@template update_password_failure} +/// Thrown during the password modification process if a failure occurs. +/// {@endtemplate} abstract class UpdatePasswordFailureInterface extends AuthenticationFailureInterface { UpdatePasswordFailureInterface(super.code, super.msg); @@ -277,9 +282,22 @@ abstract class UpdatePasswordFailureInterface UpdatePasswordFailureInterface.fromCode(super.code) : super.fromCode(); } +/// {@template model_parsing_failure} +/// Thrown during the model parsing process if a failure occurs. +/// {@endtemplate} abstract class ModelParsingFailureInterface extends AuthenticationFailureInterface { ModelParsingFailureInterface(super.code, super.msg); ModelParsingFailureInterface.fromCode(super.code) : super.fromCode(); } + +/// {@template delete_account_failure} +/// Thrown during the account deletion if a failure occurs. +/// {@endtemplate} +abstract class DeleteAccountFailureInterface + extends AuthenticationFailureInterface { + DeleteAccountFailureInterface(super.code, super.msg); + + DeleteAccountFailureInterface.fromCode(super.code) : super.fromCode(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_base.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_base.dart new file mode 100644 index 00000000..cd994be5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_base.dart @@ -0,0 +1,382 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'exceptions.dart'; + +/// {@macro apply_action_code_failure} +class ApplyActionCodeFailureBase extends ApplyActionCodeFailureInterface { + ApplyActionCodeFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + ApplyActionCodeFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'expired-action-code': + msg = 'Action code has expired.'; + break; + case 'invalid-action-code': + msg = 'Action code is invalid.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_up_with_email_and_password_failure} +class SignUpWithEmailAndPasswordFailureBase + extends SignUpWithEmailAndPasswordFailureInterface { + SignUpWithEmailAndPasswordFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignUpWithEmailAndPasswordFailureBase.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'The email address is badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'email-already-in-use': + msg = 'An account already exists for that email.'; + break; + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + case 'weak-password': + msg = 'Please enter a stronger password.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro fetch_sign_in_methods_failure} +class FetchSignInMethodsForEmailFailureBase + extends FetchSignInMethodsForEmailFailureInterface { + FetchSignInMethodsForEmailFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + FetchSignInMethodsForEmailFailureBase.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'The email address is badly formatted.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_anonymously_failure} +class SignInAnonymouslyFailureBase extends SignInAnonymouslyFailureInterface { + SignInAnonymouslyFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInAnonymouslyFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_credential_failure} +class SignInWithCredentialFailureBase + extends SignInWithCredentialFailureInterface { + SignInWithCredentialFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithCredentialFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'account-exists-with-different-credential': + msg = 'Account exists with different credentials.'; + break; + case 'invalid-credential': + msg = 'The credential received is malformed or has expired.'; + break; + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + case 'invalid-verification-code': + msg = 'The credential verification code received is invalid.'; + break; + case 'invalid-verification-id': + msg = 'The credential verification ID received is invalid.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_google_failure} +class SignInWithGoogleFailureBase extends SignInWithCredentialFailureBase + implements SignInWithGoogleFailureInterface { + SignInWithGoogleFailureBase([super.code, super.msg]); + SignInWithGoogleFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_facebook_failure} +class SignInWithFacebookFailureBase extends SignInWithCredentialFailureBase + implements SignInWithFacebookFailureInterface { + SignInWithFacebookFailureBase([super.code, super.msg]); + SignInWithFacebookFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_apple_failure} +class SignInWithAppleFailureBase extends SignInWithCredentialFailureBase + implements SignInWithAppleFailureInterface { + SignInWithAppleFailureBase([super.code, super.msg]); + SignInWithAppleFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_twitter_failure} +class SignInWithTwitterFailureBase extends SignInWithCredentialFailureBase + implements SignInWithAppleFailureInterface { + SignInWithTwitterFailureBase([super.code, super.msg]); + SignInWithTwitterFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_email_link_failure} +class SignInWithEmailLinkFailureBase + extends SignInWithEmailLinkFailureInterface { + SignInWithEmailLinkFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithEmailLinkFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'expired-action-code': + msg = 'Action code has expired.'; + break; + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_email_and_password_failure} +class SignInWithEmailAndPasswordFailureBase + extends SignInWithEmailAndPasswordFailureInterface { + SignInWithEmailAndPasswordFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithEmailAndPasswordFailureBase.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro send_email_verification_failure} +class SendEmailVerificationFailureBase + extends SendEmailVerificationFailureInterface { + SendEmailVerificationFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SendEmailVerificationFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro send_password_reset_email_failure} +class SendPasswordResetEmailFailureBase + extends SendPasswordResetEmailFailureInterface { + SendPasswordResetEmailFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SendPasswordResetEmailFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro send_sign_in_link_email_failure} +class SendSignInLinkEmailFailureBase + extends SendSignInLinkEmailFailureInterface { + SendSignInLinkEmailFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SendSignInLinkEmailFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro confirm_password_reset_failure} +class ConfirmPasswordResetFailureBase + extends ConfirmPasswordResetFailureInterface { + ConfirmPasswordResetFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + ConfirmPasswordResetFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro verify_password_reset_code_failure} +class VerifyPasswordResetCodeFailureBase + extends VerifyPasswordResetCodeFailureInterface { + VerifyPasswordResetCodeFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + VerifyPasswordResetCodeFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro refresh_failure} +class RefreshFailureBase extends RefreshFailureInterface { + RefreshFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + RefreshFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_out_failure} +class SignOutFailureBase extends SignOutFailureInterface { + SignOutFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SignOutFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro reauthenticate_failure} +class ReauthenticateFailureBase extends ReauthenticateFailureInterface { + ReauthenticateFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + ReauthenticateFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'user-mismatch': + msg = 'Given credential does not correspond to the user.'; + break; + case 'user-not-found': + msg = 'User is not found, please create an account.'; + break; + case 'invalid-credential': + msg = 'The credential received is malformed or has expired.'; + break; + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + case 'invalid-verification-code': + msg = 'The credential verification code received is invalid.'; + break; + case 'invalid-verification-id': + msg = 'The credential verification ID received is invalid.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro update_email_failure} +class UpdateEmailFailureBase extends UpdateEmailFailureInterface { + UpdateEmailFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + UpdateEmailFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'email-already-in-use': + msg = 'An account already exists for that email.'; + break; + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro update_password_failure} +class UpdatePasswordFailureBase extends UpdatePasswordFailureInterface { + UpdatePasswordFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + UpdatePasswordFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'weak-password': + msg = 'Please enter a stronger password.'; + break; + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro model_parsing_failure} +class ModelParsingFailureBase extends ModelParsingFailureInterface { + ModelParsingFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + ModelParsingFailureBase.fromCode(super.code) : super.fromCode(); +} + +/// {@macro delete_account_failure} +class DeleteAccountFailureBase extends DeleteAccountFailureInterface { + DeleteAccountFailureBase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + DeleteAccountFailureBase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart index 58e3c409..7b17e606 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,6 +16,7 @@ part of 'exceptions.dart'; +/// {@macro apply_action_code_failure} class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface { ApplyActionCodeFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); @@ -41,6 +42,7 @@ class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface { } } +/// {@macro sign_up_with_email_and_password_failure} class SignUpWithEmailAndPasswordFailureFirebase extends SignUpWithEmailAndPasswordFailureInterface { SignUpWithEmailAndPasswordFailureFirebase([String? code, String? msg]) @@ -70,6 +72,7 @@ class SignUpWithEmailAndPasswordFailureFirebase } } +/// {@macro fetch_sign_in_methods_failure} class FetchSignInMethodsForEmailFailureFirebase extends FetchSignInMethodsForEmailFailureInterface { FetchSignInMethodsForEmailFailureFirebase([String? code, String? msg]) @@ -87,6 +90,7 @@ class FetchSignInMethodsForEmailFailureFirebase } } +/// {@macro sign_in_anonymously_failure} class SignInAnonymouslyFailureFirebase extends SignInAnonymouslyFailureInterface { SignInAnonymouslyFailureFirebase([String? code, String? msg]) @@ -104,6 +108,7 @@ class SignInAnonymouslyFailureFirebase } } +/// {@macro sign_in_with_credential_failure} class SignInWithCredentialFailureFirebase extends SignInWithCredentialFailureInterface { SignInWithCredentialFailureFirebase([String? code, String? msg]) @@ -142,6 +147,7 @@ class SignInWithCredentialFailureFirebase } } +/// {@macro sign_in_with_google_failure} class SignInWithGoogleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithGoogleFailureInterface { @@ -149,6 +155,7 @@ class SignInWithGoogleFailureFirebase SignInWithGoogleFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro sign_in_with_facebook_failure} class SignInWithFacebookFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithFacebookFailureInterface { @@ -156,12 +163,14 @@ class SignInWithFacebookFailureFirebase SignInWithFacebookFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro sign_in_with_apple_failure} class SignInWithAppleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { SignInWithAppleFailureFirebase([super.code, super.msg]); SignInWithAppleFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro sign_in_with_twitter_failure} class SignInWithTwitterFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { @@ -169,6 +178,7 @@ class SignInWithTwitterFailureFirebase SignInWithTwitterFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro sign_in_with_email_link_failure} class SignInWithEmailLinkFailureFirebase extends SignInWithEmailLinkFailureInterface { SignInWithEmailLinkFailureFirebase([String? code, String? msg]) @@ -192,6 +202,7 @@ class SignInWithEmailLinkFailureFirebase } } +/// {@macro sign_in_with_email_and_password_failure} class SignInWithEmailAndPasswordFailureFirebase extends SignInWithEmailAndPasswordFailureInterface { SignInWithEmailAndPasswordFailureFirebase([String? code, String? msg]) @@ -218,6 +229,7 @@ class SignInWithEmailAndPasswordFailureFirebase } } +/// {@macro send_email_verification_failure} class SendEmailVerificationFailureFirebase extends SendEmailVerificationFailureInterface { SendEmailVerificationFailureFirebase([String? code, String? msg]) @@ -226,6 +238,7 @@ class SendEmailVerificationFailureFirebase SendEmailVerificationFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro send_password_reset_email_failure} class SendPasswordResetEmailFailureFirebase extends SendPasswordResetEmailFailureInterface { SendPasswordResetEmailFailureFirebase([String? code, String? msg]) @@ -233,6 +246,7 @@ class SendPasswordResetEmailFailureFirebase SendPasswordResetEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro send_sign_in_link_email_failure} class SendSignInLinkEmailFailureFirebase extends SendSignInLinkEmailFailureInterface { SendSignInLinkEmailFailureFirebase([String? code, String? msg]) @@ -241,6 +255,7 @@ class SendSignInLinkEmailFailureFirebase SendSignInLinkEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro confirm_password_reset_failure} class ConfirmPasswordResetFailureFirebase extends ConfirmPasswordResetFailureInterface { ConfirmPasswordResetFailureFirebase([String? code, String? msg]) @@ -249,6 +264,7 @@ class ConfirmPasswordResetFailureFirebase ConfirmPasswordResetFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro verify_password_reset_code_failure} class VerifyPasswordResetCodeFailureFirebase extends VerifyPasswordResetCodeFailureInterface { VerifyPasswordResetCodeFailureFirebase([String? code, String? msg]) @@ -258,12 +274,14 @@ class VerifyPasswordResetCodeFailureFirebase : super.fromCode(); } +/// {@macro refresh_failure} class RefreshFailureFirebase extends RefreshFailureInterface { RefreshFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); RefreshFailureFirebase.fromCode(super.code) : super.fromCode(); } +/// {@macro sign_out_failure} class SignOutFailureFirebase extends SignOutFailureInterface { SignOutFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); @@ -271,13 +289,7 @@ class SignOutFailureFirebase extends SignOutFailureInterface { SignOutFailureFirebase.fromCode(super.code) : super.fromCode(); } -class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface { - GetIdTokenFailureFirebase([String? code, String? msg]) - : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); - - GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode(); -} - +/// {@macro reauthenticate_failure} class ReauthenticateFailureFirebase extends ReauthenticateFailureInterface { ReauthenticateFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); @@ -311,6 +323,7 @@ class ReauthenticateFailureFirebase extends ReauthenticateFailureInterface { } } +/// {@macro update_email_failure} class UpdateEmailFailureFirebase extends UpdateEmailFailureInterface { UpdateEmailFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); @@ -332,6 +345,7 @@ class UpdateEmailFailureFirebase extends UpdateEmailFailureInterface { } } +/// {@macro update_password_failure} class UpdatePasswordFailureFirebase extends UpdatePasswordFailureInterface { UpdatePasswordFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); @@ -350,9 +364,27 @@ class UpdatePasswordFailureFirebase extends UpdatePasswordFailureInterface { } } +/// {@macro model_parsing_failure} class ModelParsingFailureFirebase extends ModelParsingFailureInterface { ModelParsingFailureFirebase([String? code, String? msg]) : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); ModelParsingFailureFirebase.fromCode(super.code) : super.fromCode(); } + +/// {@macro delete_account_failure} +class DeleteAccountFailureFirebase extends DeleteAccountFailureInterface { + DeleteAccountFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + DeleteAccountFailureFirebase.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_mock.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_mock.dart new file mode 100644 index 00000000..57a960e4 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_mock.dart @@ -0,0 +1,382 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'exceptions.dart'; + +/// {@macro apply_action_code_failure} +class ApplyActionCodeFailureMock extends ApplyActionCodeFailureInterface { + ApplyActionCodeFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + ApplyActionCodeFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'expired-action-code': + msg = 'Action code has expired.'; + break; + case 'invalid-action-code': + msg = 'Action code is invalid.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_up_with_email_and_password_failure} +class SignUpWithEmailAndPasswordFailureMock + extends SignUpWithEmailAndPasswordFailureInterface { + SignUpWithEmailAndPasswordFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignUpWithEmailAndPasswordFailureMock.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'The email address is badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'email-already-in-use': + msg = 'An account already exists for that email.'; + break; + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + case 'weak-password': + msg = 'Please enter a stronger password.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro fetch_sign_in_methods_failure} +class FetchSignInMethodsForEmailFailureMock + extends FetchSignInMethodsForEmailFailureInterface { + FetchSignInMethodsForEmailFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + FetchSignInMethodsForEmailFailureMock.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'The email address is badly formatted.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_anonymously_failure} +class SignInAnonymouslyFailureMock extends SignInAnonymouslyFailureInterface { + SignInAnonymouslyFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInAnonymouslyFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_credential_failure} +class SignInWithCredentialFailureMock + extends SignInWithCredentialFailureInterface { + SignInWithCredentialFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithCredentialFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'account-exists-with-different-credential': + msg = 'Account exists with different credentials.'; + break; + case 'invalid-credential': + msg = 'The credential received is malformed or has expired.'; + break; + case 'operation-not-allowed': + msg = 'Operation is not allowed. Please contact support.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + case 'invalid-verification-code': + msg = 'The credential verification code received is invalid.'; + break; + case 'invalid-verification-id': + msg = 'The credential verification ID received is invalid.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_google_failure} +class SignInWithGoogleFailureMock extends SignInWithCredentialFailureMock + implements SignInWithGoogleFailureInterface { + SignInWithGoogleFailureMock([super.code, super.msg]); + SignInWithGoogleFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_facebook_failure} +class SignInWithFacebookFailureMock extends SignInWithCredentialFailureMock + implements SignInWithFacebookFailureInterface { + SignInWithFacebookFailureMock([super.code, super.msg]); + SignInWithFacebookFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_apple_failure} +class SignInWithAppleFailureMock extends SignInWithCredentialFailureMock + implements SignInWithAppleFailureInterface { + SignInWithAppleFailureMock([super.code, super.msg]); + SignInWithAppleFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_twitter_failure} +class SignInWithTwitterFailureMock extends SignInWithCredentialFailureMock + implements SignInWithAppleFailureInterface { + SignInWithTwitterFailureMock([super.code, super.msg]); + SignInWithTwitterFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_in_with_email_link_failure} +class SignInWithEmailLinkFailureMock + extends SignInWithEmailLinkFailureInterface { + SignInWithEmailLinkFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithEmailLinkFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'expired-action-code': + msg = 'Action code has expired.'; + break; + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro sign_in_with_email_and_password_failure} +class SignInWithEmailAndPasswordFailureMock + extends SignInWithEmailAndPasswordFailureInterface { + SignInWithEmailAndPasswordFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SignInWithEmailAndPasswordFailureMock.fromCode(String code) + : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'user-disabled': + msg = 'This user has been disabled. Please contact support for help.'; + break; + case 'user-not-found': + msg = 'Email is not found, please create an account.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro send_email_verification_failure} +class SendEmailVerificationFailureMock + extends SendEmailVerificationFailureInterface { + SendEmailVerificationFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SendEmailVerificationFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro send_password_reset_email_failure} +class SendPasswordResetEmailFailureMock + extends SendPasswordResetEmailFailureInterface { + SendPasswordResetEmailFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + SendPasswordResetEmailFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro send_sign_in_link_email_failure} +class SendSignInLinkEmailFailureMock + extends SendSignInLinkEmailFailureInterface { + SendSignInLinkEmailFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SendSignInLinkEmailFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro confirm_password_reset_failure} +class ConfirmPasswordResetFailureMock + extends ConfirmPasswordResetFailureInterface { + ConfirmPasswordResetFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + ConfirmPasswordResetFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro verify_password_reset_code_failure} +class VerifyPasswordResetCodeFailureMock + extends VerifyPasswordResetCodeFailureInterface { + VerifyPasswordResetCodeFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + VerifyPasswordResetCodeFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro refresh_failure} +class RefreshFailureMock extends RefreshFailureInterface { + RefreshFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + RefreshFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro sign_out_failure} +class SignOutFailureMock extends SignOutFailureInterface { + SignOutFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + SignOutFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro reauthenticate_failure} +class ReauthenticateFailureMock extends ReauthenticateFailureInterface { + ReauthenticateFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + ReauthenticateFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'user-mismatch': + msg = 'Given credential does not correspond to the user.'; + break; + case 'user-not-found': + msg = 'User is not found, please create an account.'; + break; + case 'invalid-credential': + msg = 'The credential received is malformed or has expired.'; + break; + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'wrong-password': + msg = 'Incorrect password, please try again.'; + break; + case 'invalid-verification-code': + msg = 'The credential verification code received is invalid.'; + break; + case 'invalid-verification-id': + msg = 'The credential verification ID received is invalid.'; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro update_email_failure} +class UpdateEmailFailureMock extends UpdateEmailFailureInterface { + UpdateEmailFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + UpdateEmailFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'invalid-email': + msg = 'Email is not valid or badly formatted.'; + break; + case 'email-already-in-use': + msg = 'An account already exists for that email.'; + break; + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro update_password_failure} +class UpdatePasswordFailureMock extends UpdatePasswordFailureInterface { + UpdatePasswordFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + UpdatePasswordFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'weak-password': + msg = 'Please enter a stronger password.'; + break; + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} + +/// {@macro model_parsing_failure} +class ModelParsingFailureMock extends ModelParsingFailureInterface { + ModelParsingFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + ModelParsingFailureMock.fromCode(super.code) : super.fromCode(); +} + +/// {@macro delete_account_failure} +class DeleteAccountFailureMock extends DeleteAccountFailureInterface { + DeleteAccountFailureMock([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); + + DeleteAccountFailureMock.fromCode(String code) : super.fromCode(code) { + switch (code) { + case 'requires-recent-login': + msg = "User's last sign-in time does not meet the security threshold."; + break; + default: + this.code = 'unknown'; + msg = 'An unknown error occurred.'; + } + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/extensions/build_context_extension.dart b/packages/wyatt_authentication_bloc/lib/src/core/extensions/build_context_extension.dart new file mode 100644 index 00000000..d473dace --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/extensions/build_context_extension.dart @@ -0,0 +1,98 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/authentication_change_event/authentication_change_event.dart'; +import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart'; + +/// Extension that helps to quickly access useful resources +/// from the context. +extension BuildContextExtension on BuildContext { + /// Read session in context from a specific AuthenticationCubit type [T] + AuthenticationSession? + readSessionFrom, Data>() => + read().currentSession(); + + /// Watch session in context from a specific AuthenticationCubit type [T] + AuthenticationSession? + watchSessionFrom, Data>() => + watch().currentSession(); + + /// Read session in context from generic AuthenticationCubit type + AuthenticationSession? readSession() => + read>().currentSession(); + + /// Watch session in context from generic AuthenticationCubit type + AuthenticationSession? watchSession() => + watch>().currentSession(); + + /// Read event in context from a specific AuthenticationCubit type [T] + AuthenticationChangeEvent? + readEventFrom, Data>() => + readSessionFrom()?.latestEvent; + + /// Watch event in context from a specific AuthenticationCubit type [T] + AuthenticationChangeEvent? + watchEventFrom, Data>() => + watchSessionFrom()?.latestEvent; + + /// Read event in context from generic AuthenticationCubit type + AuthenticationChangeEvent? readEvent() => + readSession()?.latestEvent; + + /// Watch event in context from generic AuthenticationCubit type + AuthenticationChangeEvent? watchEvent() => + watchSession()?.latestEvent; + + /// Read account in context from a specific AuthenticationCubit type [T] + Account? readAccountFrom, Data>() => + readSessionFrom()?.account; + + /// Watch account in context from a specific AuthenticationCubit type [T] + Account? watchAccountFrom, Data>() => + watchSessionFrom()?.account; + + /// Read account in context from generic AuthenticationCubit type + Account? readAccount() => readSession()?.account; + + /// Watch account in context from generic AuthenticationCubit type + Account? watchAccount() => watchSession()?.account; + + /// Read data in context from a specific AuthenticationCubit type [T] + Data? readDataFrom, Data>() => + readSessionFrom()?.data; + + /// Watch data in context from a specific AuthenticationCubit type [T] + Data? watchDataFrom, Data>() => + watchSessionFrom()?.data; + + /// Read data in context from generic AuthenticationCubit type + Data? readData() => readSession()?.data; + + /// Watch data in context from generic AuthenticationCubit type + Data? watchData() => watchSession()?.data; + + /// Check if user is authenticated from a + /// specific AuthenticationCubit type [T] + bool isAuthenticatedFrom, Data>() => + readEventFrom() is AuthenticatedChangeEvent; + + /// Check if user is authenticated from generic AuthenticationCubit type + bool isAuthenticated() => readEvent() is AuthenticatedChangeEvent; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/utils/custom_routine.dart b/packages/wyatt_authentication_bloc/lib/src/core/utils/custom_routine.dart new file mode 100644 index 00000000..ff58f8df --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/utils/custom_routine.dart @@ -0,0 +1,72 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// {@template custom_routine} +/// A custom routine that can be used to call a routine and +/// attach custom logic to it. +/// {@endtemplate} +class CustomRoutine { + /// {@macro custom_routine} + const CustomRoutine({ + required this.routine, + required this.attachedLogic, + required this.onError, + required this.onSuccess, + }); + + /// The routine to be called + final FutureOr> Function() routine; + + /// The custom logic to be attached to the routine + final FutureOr> Function( + Result routineResult, + ) attachedLogic; + + /// The callback to be called when an error occurs + final void Function(AppException exception) onError; + + /// The callback to be called when no error occurs + final void Function(R result, Data? data) onSuccess; + + /// Calls the routine and calls the custom attached logic + FutureOr call() async { + final result = await routine.call(); + + // Call custom logic + final customRoutineResult = await attachedLogic.call(result); + + // Check for errors + if (result.isErr) { + onError.call(result.err!); + + return; + } + if (customRoutineResult.isErr) { + onError.call(customRoutineResult.err!); + + return; + } + + // If no error + return onSuccess.call(result.ok as R, customRoutineResult.ok); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart b/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart new file mode 100644 index 00000000..ec95768b --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/utils/forms.dart @@ -0,0 +1,101 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +/// This class contains all the forms used in the authentication process. +abstract class Forms { + /// Builds a sign in form. + static WyattForm buildSignInForm( + FormInputValidator? customEmailValidator, + FormInputValidator? customPasswordValidator, + ) => + WyattFormImpl( + [ + FormInput( + AuthFormField.email, + customEmailValidator ?? const Email.pure(), + ), + FormInput( + AuthFormField.password, + customPasswordValidator ?? const Password.pure(), + ) + ], + name: AuthFormName.signInForm, + ); + + /// Builds a sign up form. + static WyattForm buildSignUpForm( + FormInputValidator? customEmailValidator, + FormInputValidator? customPasswordValidator, + // ignore: strict_raw_type + List? extraSignUpInputs, + ) => + WyattFormImpl( + [ + FormInput( + AuthFormField.email, + customEmailValidator ?? const Email.pure(), + ), + FormInput( + AuthFormField.password, + customPasswordValidator ?? const Password.pure(), + ), + ...extraSignUpInputs ?? [] + ], + name: AuthFormName.signUpForm, + ); + + /// Builds a password reset form. + static WyattForm buildPasswordResetForm( + FormInputValidator? customEmailValidator, + ) => + WyattFormImpl( + [ + FormInput( + AuthFormField.email, + customEmailValidator ?? const Email.pure(), + ), + ], + name: AuthFormName.passwordResetForm, + ); + + /// Builds an edit account form. + static WyattForm buildEditAccountForm( + FormInputValidator? customEmailValidator, + FormInputValidator? customPasswordValidator, + // ignore: strict_raw_type + List? extraEditAccountInputs, + ) => + WyattFormImpl( + [ + FormInput( + AuthFormField.email, + customEmailValidator ?? const Email.pure(), + metadata: const FormInputMetadata(isRequired: false), + ), + FormInput( + AuthFormField.password, + customPasswordValidator ?? const Password.pure(), + metadata: const FormInputMetadata(isRequired: false), + ), + ...extraEditAccountInputs ?? [] + ], + validationStrategy: const OnlyRequiredInputValidator(), + name: AuthFormName.editAccountForm, + ); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data.dart b/packages/wyatt_authentication_bloc/lib/src/data/data.dart index 35d3fdd1..581cd9c5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart index 24eff56f..843f681b 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,6 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'local/authentication_cache_data_source_impl.dart'; -export 'remote/authentication_firebase_data_source_impl.dart'; -export 'remote/authentication_mock_data_source_impl.dart'; +export 'local/local.dart'; +export 'remote/remote.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_firebase_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_firebase_cache_data_source_impl.dart new file mode 100644 index 00000000..53aef590 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_firebase_cache_data_source_impl.dart @@ -0,0 +1,56 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +/// {@template authentication_firebase_cache_data_source_impl} +/// A data source that manages the cache strategy. +/// This implementation uses Firebase. +/// {@endtemplate} +class AuthenticationFirebaseCacheDataSourceImpl + extends AuthenticationCacheDataSource { + /// {@macro authentication_firebase_cache_data_source_impl} + AuthenticationFirebaseCacheDataSourceImpl({ + FirebaseAuth? firebaseAuth, + }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance; + + final FirebaseAuth _firebaseAuth; + + // Already done by Firebase + @override + Future cacheAccount(Account account) => Future.value(); + + @override + Future getCachedAccount() async { + final currentUser = _firebaseAuth.currentUser; + if (currentUser == null) { + return null; + } + + final jwt = await currentUser.getIdToken(true); + final currentAccount = AccountModel.fromFirebaseUser( + currentUser, + accessToken: jwt, + ); + + return currentAccount; + } + + // Already done by Firebase + @override + Future removeCachedAccount() => Future.value(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_secure_storage_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_secure_storage_cache_data_source_impl.dart new file mode 100644 index 00000000..a59f3383 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_secure_storage_cache_data_source_impl.dart @@ -0,0 +1,75 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/storage.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +/// {@template authentication_secure_storage_cache_data_source_impl} +/// A data source that manages the cache strategy. +/// This implementation uses Secure Storage. +/// {@endtemplate} +class AuthenticationSecureStorageCacheDataSourceImpl + extends AuthenticationCacheDataSource { + /// {@macro authentication_secure_storage_cache_data_source_impl} + const AuthenticationSecureStorageCacheDataSourceImpl({ + FlutterSecureStorage? secureStorage, + }) : _secureStorage = secureStorage ?? const FlutterSecureStorage(); + + final FlutterSecureStorage _secureStorage; + + @override + Future cacheAccount(Account account) async { + await _secureStorage.write( + key: AuthStorage.id, + value: account.id, + ); + await _secureStorage.write( + key: AuthStorage.email, + value: account.email, + ); + await _secureStorage.write( + key: AuthStorage.accessToken, + value: account.accessToken, + ); + } + + @override + Future getCachedAccount() async { + final id = await _secureStorage.read(key: AuthStorage.id); + final email = await _secureStorage.read(key: AuthStorage.email); + final accessToken = await _secureStorage.read(key: AuthStorage.accessToken); + + if (id == null || email == null || accessToken == null) { + return null; + } + + final currentAccount = AccountModel.fromSecureStorage( + id: id, + email: email, + accessToken: accessToken, + ); + + return currentAccount; + } + + @override + Future removeCachedAccount() async { + await _secureStorage.delete(key: AuthStorage.id); + await _secureStorage.delete(key: AuthStorage.email); + await _secureStorage.delete(key: AuthStorage.accessToken); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_session_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_session_data_source_impl.dart new file mode 100644 index 00000000..1287d889 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_session_data_source_impl.dart @@ -0,0 +1,45 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:rxdart/subjects.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_session_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; + +/// {@template authentication_session_data_source_impl} +/// A data source that manages the current session. +/// {@endtemplate} +class AuthenticationSessionDataSourceImpl + extends AuthenticationSessionDataSource { + /// {@macro authentication_session_data_source_impl} + AuthenticationSessionDataSourceImpl(); + + final StreamController> _sessionStream = + BehaviorSubject(); + + @override + void addSession(AuthenticationSession session) { + _sessionStream.add(session); + } + + @override + Future> currentSession() => sessionStream().last; + + @override + Stream> sessionStream() => + _sessionStream.stream.asBroadcastStream(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/local.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/local.dart new file mode 100644 index 00000000..b9bf04e1 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/local.dart @@ -0,0 +1,19 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'authentication_firebase_cache_data_source_impl.dart'; +export 'authentication_secure_storage_cache_data_source_impl.dart'; +export 'authentication_session_data_source_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_base_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_base_data_source.dart new file mode 100644 index 00000000..bbdd8dd9 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_base_data_source.dart @@ -0,0 +1,106 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +/// {@template authentication_base_data_source} +/// Base class for custom [AuthenticationRemoteDataSource] implementations. +/// It implements all methods as throwing [UnimplementedError]s. +/// {@endtemplate} +class AuthenticationBaseDataSource + extends AuthenticationRemoteDataSource { + /// {@macro authentication_base_data_source} + const AuthenticationBaseDataSource(); + + @override + Future confirmPasswordReset({ + required String code, + required String newPassword, + }) { + throw UnimplementedError(); + } + + @override + Future delete() { + throw UnimplementedError(); + } + + @override + Future reauthenticate() { + throw UnimplementedError(); + } + + @override + Future refresh() { + throw UnimplementedError(); + } + + @override + Future sendEmailVerification() { + throw UnimplementedError(); + } + + @override + Future sendPasswordResetEmail({required String email}) { + throw UnimplementedError(); + } + + @override + Future signInAnonymously() { + throw UnimplementedError(); + } + + @override + Future signInWithEmailAndPassword({ + required String email, + required String password, + }) { + throw UnimplementedError(); + } + + @override + Future signInWithGoogle() { + throw UnimplementedError(); + } + + @override + Future signOut() { + throw UnimplementedError(); + } + + @override + Future signUpWithEmailAndPassword({ + required String email, + required String password, + }) { + throw UnimplementedError(); + } + + @override + Future updateEmail({required String email}) { + throw UnimplementedError(); + } + + @override + Future updatePassword({required String password}) { + throw UnimplementedError(); + } + + @override + Future verifyPasswordResetCode({required String code}) { + throw UnimplementedError(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart index 8a4ce432..f2552b87 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,22 +14,74 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/data/models/account_model_firebase.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'dart:async'; + +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:rxdart/subjects.dart'; +import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +import 'package:wyatt_authentication_bloc/src/data/models/models.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -class AuthenticationFirebaseDataSourceImpl - extends AuthenticationRemoteDataSource { +/// {@template authentication_firebase_data_source_impl} +/// Implementation of [AuthenticationRemoteDataSource] using Firebase. +/// {@endtemplate} +class AuthenticationFirebaseDataSourceImpl + extends AuthenticationRemoteDataSource { + /// {@macro authentication_firebase_data_source_impl} AuthenticationFirebaseDataSourceImpl({ FirebaseAuth? firebaseAuth, GoogleSignIn? googleSignIn, }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, - _googleSignIn = googleSignIn ?? GoogleSignIn(); + _googleSignIn = googleSignIn ?? GoogleSignIn() { + _latestCredentials = BehaviorSubject(); + } + + late StreamController _latestCredentials; final FirebaseAuth _firebaseAuth; final GoogleSignIn _googleSignIn; - UserCredential? _latestCreds; + Future _addToCredentialStream( + UserCredential userCredential, + ) async { + final currentUser = _firebaseAuth.currentUser; + final jwt = await currentUser?.getIdToken(true); + final account = AccountModel.fromFirebaseUserCredential( + userCredential, + accessToken: jwt, + ); + + _latestCredentials.add(userCredential); + + return account; + } + + // SignUp/SignIn methods ==================================================== + + /// {@macro signup_pwd} + @override + Future signUpWithEmailAndPassword({ + required String email, + required String password, + }) async { + try { + final userCredential = await _firebaseAuth.createUserWithEmailAndPassword( + email: email, + password: password, + ); + + return _addToCredentialStream(userCredential); + } on FirebaseAuthException catch (e) { + throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw SignUpWithEmailAndPasswordFailureFirebase(); + } + } + + /// {@macro signin_pwd} @override Future signInWithEmailAndPassword({ required String email, @@ -40,9 +92,8 @@ class AuthenticationFirebaseDataSourceImpl email: email, password: password, ); - _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + + return _addToCredentialStream(userCredential); } on FirebaseAuthException catch (e) { throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); } catch (_) { @@ -50,110 +101,13 @@ class AuthenticationFirebaseDataSourceImpl } } - @override - - /// {@macro signup} - Future signUp({ - required String email, - required String password, - }) async { - try { - final userCredential = await _firebaseAuth.createUserWithEmailAndPassword( - email: email, - password: password, - ); - _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); - } on FirebaseAuthException catch (e) { - throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignUpWithEmailAndPasswordFailureFirebase(); - } - } - - @override - Future signOut() async { - try { - _latestCreds = null; - await _firebaseAuth.signOut(); - } catch (_) { - throw SignOutFailureFirebase(); - } - } - - @override - Future getIdentityToken() async { - try { - final token = await _firebaseAuth.currentUser?.getIdToken(); - if (token.isNotNull) { - return token!; - } else { - throw Exception(); // Get caught just after. - } - } on FirebaseAuthException catch (e) { - throw GetIdTokenFailureFirebase.fromCode(e.code); - } catch (_) { - throw GetIdTokenFailureFirebase(); - } - } - - @override - Stream streamAccount() => - _firebaseAuth.userChanges().map((user) { - try { - return AccountModelFirebase.fromFirebaseUser(user); - } on FirebaseAuthException { - return null; - } - }); - - @override - Future confirmPasswordReset({ - required String code, - required String newPassword, - }) async { - try { - await _firebaseAuth.confirmPasswordReset( - code: code, - newPassword: newPassword, - ); - } on FirebaseAuthException catch (e) { - throw ConfirmPasswordResetFailureFirebase.fromCode(e.code); - } catch (_) { - throw ConfirmPasswordResetFailureFirebase(); - } - } - - @override - Future sendEmailVerification() async { - try { - await _firebaseAuth.currentUser!.sendEmailVerification(); - } on FirebaseAuthException catch (e) { - throw SendEmailVerificationFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendEmailVerificationFailureFirebase(); - } - } - - @override - Future sendPasswordResetEmail({required String email}) async { - try { - await _firebaseAuth.sendPasswordResetEmail(email: email); - } on FirebaseAuthException catch (e) { - throw SendPasswordResetEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendPasswordResetEmailFailureFirebase(); - } - } - + /// {@macro signin_anom} @override Future signInAnonymously() async { try { final userCredential = await _firebaseAuth.signInAnonymously(); - _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + + return _addToCredentialStream(userCredential); } on FirebaseAuthException catch (e) { throw SignInAnonymouslyFailureFirebase.fromCode(e.code); } catch (_) { @@ -161,6 +115,7 @@ class AuthenticationFirebaseDataSourceImpl } } + /// {@macro signin_google} @override Future signInWithGoogle() async { try { @@ -180,9 +135,7 @@ class AuthenticationFirebaseDataSourceImpl final userCredential = await _firebaseAuth.signInWithCredential(credential); - _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + return _addToCredentialStream(userCredential); } on FirebaseAuthException catch (e) { throw SignInWithGoogleFailureFirebase.fromCode(e.code); } catch (_) { @@ -190,6 +143,159 @@ class AuthenticationFirebaseDataSourceImpl } } + /// {@macro signout} + @override + Future signOut() async { + try { + _latestCredentials.add(null); + await _firebaseAuth.signOut(); + } catch (_) { + throw SignOutFailureFirebase(); + } + } + + // Account management methods =============================================== + + /// {@macro refresh} + @override + Future refresh() async { + try { + final jwt = await _firebaseAuth.currentUser?.getIdToken(true); + final account = AccountModel.fromFirebaseUser( + _firebaseAuth.currentUser, + accessToken: jwt, + ); + + return account; + } on FirebaseAuthException catch (e) { + throw RefreshFailureFirebase.fromCode(e.code); + } catch (_) { + throw RefreshFailureFirebase(); + } + } + + /// {@macro reauthenticate} + @override + Future reauthenticate() async { + final latestCreds = + await _latestCredentials.stream.asBroadcastStream().last; + try { + if (latestCreds?.credential != null) { + await _firebaseAuth.currentUser + ?.reauthenticateWithCredential(latestCreds!.credential!); + } else { + throw Exception(); // Get caught just after. + } + + final jwt = await _firebaseAuth.currentUser?.getIdToken(true); + final account = AccountModel.fromFirebaseUser( + _firebaseAuth.currentUser, + accessToken: jwt, + ); + + return account; + } on FirebaseAuthException catch (e) { + throw ReauthenticateFailureFirebase.fromCode(e.code); + } catch (_) { + throw ReauthenticateFailureFirebase(); + } + } + + /// {@macro update_email} + @override + Future updateEmail({required String email}) async { + try { + await _firebaseAuth.currentUser!.updateEmail(email); + final jwt = await _firebaseAuth.currentUser!.getIdToken(true); + final account = AccountModel.fromFirebaseUser( + _firebaseAuth.currentUser, + accessToken: jwt, + ); + + return account; + } on FirebaseAuthException catch (e) { + throw UpdateEmailFailureFirebase.fromCode(e.code); + } catch (_) { + throw UpdateEmailFailureFirebase(); + } + } + + /// {@macro update_password} + @override + Future updatePassword({required String password}) async { + try { + await _firebaseAuth.currentUser!.updatePassword(password); + final jwt = await _firebaseAuth.currentUser!.getIdToken(true); + final account = AccountModel.fromFirebaseUser( + _firebaseAuth.currentUser, + accessToken: jwt, + ); + + return account; + } on FirebaseAuthException catch (e) { + throw UpdatePasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw UpdatePasswordFailureFirebase(); + } + } + + /// {@macro delete} + @override + Future delete() async { + try { + await _firebaseAuth.currentUser!.delete(); + } on FirebaseAuthException catch (e) { + throw DeleteAccountFailureFirebase.fromCode(e.code); + } catch (_) { + throw DeleteAccountFailureFirebase(); + } + } + + // Email related stuff ====================================================== + + /// {@macro send_email_verification} + @override + Future sendEmailVerification() async { + try { + await _firebaseAuth.currentUser!.sendEmailVerification(); + } on FirebaseAuthException catch (e) { + throw SendEmailVerificationFailureFirebase.fromCode(e.code); + } catch (_) { + throw SendEmailVerificationFailureFirebase(); + } + } + + /// {@macro send_password_reset_email} + @override + Future sendPasswordResetEmail({required String email}) async { + try { + await _firebaseAuth.sendPasswordResetEmail(email: email); + } on FirebaseAuthException catch (e) { + throw SendPasswordResetEmailFailureFirebase.fromCode(e.code); + } catch (_) { + throw SendPasswordResetEmailFailureFirebase(); + } + } + + /// {@macro confirm_password_reset} + @override + Future confirmPasswordReset({ + required String code, + required String newPassword, + }) async { + try { + await _firebaseAuth.confirmPasswordReset( + code: code, + newPassword: newPassword, + ); + } on FirebaseAuthException catch (e) { + throw ConfirmPasswordResetFailureFirebase.fromCode(e.code); + } catch (_) { + throw ConfirmPasswordResetFailureFirebase(); + } + } + + /// {@macro verify_password_reset_code} @override Future verifyPasswordResetCode({required String code}) async { try { @@ -201,59 +307,4 @@ class AuthenticationFirebaseDataSourceImpl throw VerifyPasswordResetCodeFailureFirebase(); } } - - @override - Future refresh() async { - try { - await _firebaseAuth.currentUser!.reload(); - } on FirebaseAuthException catch (e) { - throw RefreshFailureFirebase.fromCode(e.code); - } catch (_) { - throw RefreshFailureFirebase(); - } - } - - @override - Future reauthenticateWithCredential() async { - try { - if (_latestCreds?.credential != null) { - await _firebaseAuth.currentUser - ?.reauthenticateWithCredential(_latestCreds!.credential!); - } else { - throw Exception(); // Get caught just after. - } - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); - } on FirebaseAuthException catch (e) { - throw ReauthenticateFailureFirebase.fromCode(e.code); - } catch (_) { - throw ReauthenticateFailureFirebase(); - } - } - - @override - Future updateEmail({required String email}) async { - try { - await _firebaseAuth.currentUser!.updateEmail(email); - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); - } on FirebaseAuthException catch (e) { - throw UpdateEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw UpdateEmailFailureFirebase(); - } - } - - @override - Future updatePassword({required String password}) async { - try { - await _firebaseAuth.currentUser!.updatePassword(password); - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); - } on FirebaseAuthException catch (e) { - throw UpdatePasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw UpdatePasswordFailureFirebase(); - } - } } diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_mock_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_mock_data_source_impl.dart index 1ee3a767..ff876dd5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_mock_data_source_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_mock_data_source_impl.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,26 +14,37 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'dart:async'; import 'dart:math'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource { +/// {@template authentication_mock_data_source_impl} +/// Implementation of [AuthenticationRemoteDataSource] using Mocks. +/// {@endtemplate} +class AuthenticationMockDataSourceImpl + extends AuthenticationRemoteDataSource { + /// {@macro authentication_mock_data_source_impl} AuthenticationMockDataSourceImpl({ - this.idToken = 'fake-id-token', - this.registeredAccounts, + this.mockData = const { + 'test@test.fr': Pair('test12', '1'), + 'alice@test.fr': Pair('alice12', '2'), + 'bob@test.fr': Pair('bob1234', '3'), + }, + this.accessToken = 'mock_access_token', }); - Pair? _connectedMock; - Pair? _registeredMock; - DateTime _lastSignInTime = DateTime.now(); - final StreamController _streamAccount = StreamController() - ..add(null); - final List>? registeredAccounts; - final String idToken; + /// Mock data. + /// Format: > + final Map> mockData; + /// Current user. + Account? _currentUser; + + /// Access token. + final String accessToken; + + /// A random delay to simulate network latency. Future _randomDelay() async { await Future.delayed( Duration(milliseconds: Random().nextInt(400) + 200), @@ -41,231 +52,150 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource { return; } + // SignUp/SignIn methods ==================================================== + + /// {@macro signup_pwd} @override - Future confirmPasswordReset({ - required String code, - required String newPassword, + Future signUpWithEmailAndPassword({ + required String email, + required String password, }) async { await _randomDelay(); - } + mockData[email] = Pair(password, '4'); - @override - Future getIdentityToken() async { - await _randomDelay(); - return idToken; - } - - @override - Future refresh() async { - await _randomDelay(); - if (_connectedMock.isNull) { - throw RefreshFailureFirebase(); - } - final refresh = DateTime.now(); - final mock = (_connectedMock?.left as AccountModel?) - ?.copyWith(lastSignInTime: refresh); - _connectedMock = _connectedMock?.copyWith(left: mock); - _streamAccount.add(mock); - } - - @override - Future sendEmailVerification() async { - await _randomDelay(); - if (_connectedMock.isNotNull) { - final refresh = DateTime.now(); - final mock = (_connectedMock?.left as AccountModel?)?.copyWith( - emailVerified: false, - lastSignInTime: refresh, - ); - _streamAccount.add(mock); - _connectedMock = _connectedMock?.copyWith(left: mock); - return; - } - throw SendEmailVerificationFailureFirebase(); - } - - @override - Future sendPasswordResetEmail({required String email}) async { - await _randomDelay(); - if (registeredAccounts.isNotNull) { - final accounts = - registeredAccounts?.where((pair) => pair.left?.email == email); - if (accounts.isNotNullOrEmpty) { - return; - } - } - if (_registeredMock.isNotNull) { - if (_registeredMock?.left?.email != email) { - throw SendPasswordResetEmailFailureFirebase(); - } - return; - } - throw SendPasswordResetEmailFailureFirebase(); - } - - @override - Future signInAnonymously() async { - await _randomDelay(); - final creation = DateTime.now(); - final mock = AccountModel( - uid: 'mock-id-anom', - emailVerified: false, - isAnonymous: true, - providerId: 'wyatt-studio.fr', - creationTime: creation, - lastSignInTime: creation, - isNewUser: creation == creation, - ); - _streamAccount.add(mock); - _connectedMock = _connectedMock?.copyWith(left: mock); - _lastSignInTime = DateTime.now(); - return Future.value(mock); - } - - @override - Future signInWithGoogle() async { - await _randomDelay(); - final creation = DateTime.now(); - final mock = AccountModel( - uid: 'mock-id-google', - emailVerified: true, + return _currentUser = Account( + id: '4', isAnonymous: false, - providerId: 'google.com', - creationTime: creation, - lastSignInTime: creation, - isNewUser: creation == creation, + emailVerified: false, + providerId: 'mock', + email: email, + accessToken: accessToken, ); - _streamAccount.add(mock); - _connectedMock = _connectedMock?.copyWith(left: mock); - _lastSignInTime = DateTime.now(); - return Future.value(mock); } + /// {@macro signin_pwd} @override Future signInWithEmailAndPassword({ required String email, required String password, }) async { await _randomDelay(); - if (registeredAccounts.isNotNull) { - final accounts = - registeredAccounts?.where((pair) => pair.left?.email == email); - if (accounts.isNotNullOrEmpty) { - final account = accounts?.first; - if (account?.right != password) { - throw SignInWithCredentialFailureFirebase.fromCode('wrong-password'); - } - _streamAccount.add(account!.left); - _connectedMock = account.copyWith(); - return account.left!; - } + final pair = mockData[email]; + + if (pair == null || pair.left != password) { + throw SignInWithEmailAndPasswordFailureMock(); } - if (_registeredMock.isNotNull) { - if (_registeredMock?.left?.email != email) { - throw SignInWithCredentialFailureFirebase.fromCode('user-not-found'); - } - if (_registeredMock?.right != password) { - throw SignInWithCredentialFailureFirebase.fromCode('wrong-password'); - } - _streamAccount.add(_registeredMock!.left); - _connectedMock = _registeredMock!.copyWith(); - _lastSignInTime = DateTime.now(); - return _registeredMock!.left!; - } - throw SignInWithCredentialFailureFirebase(); + + return _currentUser = Account( + id: pair.right!, + isAnonymous: false, + emailVerified: true, + providerId: 'mock', + email: email, + accessToken: accessToken, + ); } + /// {@macro signin_anom} + @override + Future signInAnonymously() async { + await _randomDelay(); + return _currentUser = Account( + id: '5', + isAnonymous: true, + emailVerified: false, + providerId: 'mock', + accessToken: accessToken, + ); + } + + /// {@macro signin_google} + @override + Future signInWithGoogle() async { + await _randomDelay(); + return _currentUser = Account( + id: '6', + isAnonymous: false, + emailVerified: true, + providerId: 'google.com', + email: 'mock@gmail.com', + accessToken: accessToken, + ); + } + + /// {@macro signout} @override Future signOut() async { - _connectedMock = null; - _streamAccount.add(null); - } - - @override - Future signUp({ - required String email, - required String password, - }) async { await _randomDelay(); - if (registeredAccounts.isNotNull) { - final accounts = - registeredAccounts?.where((pair) => pair.left?.email == email); - if (accounts.isNotNullOrEmpty) { - throw SignUpWithEmailAndPasswordFailureFirebase.fromCode( - 'email-already-in-use', - ); - } - } - if (_registeredMock?.left?.email == email) { - throw SignUpWithEmailAndPasswordFailureFirebase.fromCode( - 'email-already-in-use', - ); - } - final creation = DateTime.now(); - final mock = AccountModel( - uid: 'mock-id-email', - emailVerified: false, - isAnonymous: false, - providerId: 'wyatt', - email: email, - creationTime: creation, - lastSignInTime: creation, - isNewUser: creation == creation, - ); - _streamAccount.add(mock); - _registeredMock = Pair(mock, password); - _connectedMock = _registeredMock!.copyWith(); - _lastSignInTime = DateTime.now(); - return Future.value(mock); + _currentUser = null; } - @override - Stream streamAccount() => _streamAccount.stream.asBroadcastStream(); + // Account management methods =============================================== + /// {@macro refresh} + @override + Future refresh() async { + await _randomDelay(); + if (_currentUser == null) { + throw RefreshFailureMock(); + } + return _currentUser!; + } + + /// {@macro reauthenticate} + @override + Future reauthenticate() async { + await _randomDelay(); + if (_currentUser == null) { + throw ReauthenticateFailureMock(); + } + return _currentUser!; + } + + /// {@macro update_email} + @override + Future updateEmail({required String email}) async { + throw UnimplementedError(); + } + + /// {@macro update_password} + @override + Future updatePassword({required String password}) async { + throw UnimplementedError(); + } + + /// {@macro delete} + @override + Future delete() async { + throw UnimplementedError(); + } + + // Email related stuff ====================================================== + + /// {@macro send_email_verification} + @override + Future sendEmailVerification() async { + throw UnimplementedError(); + } + + /// {@macro send_password_reset_email} + @override + Future sendPasswordResetEmail({required String email}) async { + throw UnimplementedError(); + } + + /// {@macro confirm_password_reset} + @override + Future confirmPasswordReset({ + required String code, + required String newPassword, + }) async { + throw UnimplementedError(); + } + + /// {@macro verify_password_reset_code} @override Future verifyPasswordResetCode({required String code}) async { - await _randomDelay(); - return true; - } - - @override - Future reauthenticateWithCredential() async { - await _randomDelay(); - if (_connectedMock.isNull) { - throw ReauthenticateFailureFirebase(); - } - await refresh(); - _lastSignInTime = DateTime.now(); - return Future.value(_connectedMock?.left); - } - - @override - Future updateEmail({required String email}) { - final before = DateTime.now().subtract(const Duration(seconds: 10)); - if (_lastSignInTime.isBefore(before)) { - throw UpdateEmailFailureFirebase('requires-recent-login'); - } - final refresh = DateTime.now(); - final mock = (_connectedMock?.left as AccountModel?) - ?.copyWith(lastSignInTime: refresh, email: email); - _connectedMock = _connectedMock?.copyWith(left: mock); - _registeredMock = _registeredMock?.copyWith(left: mock); - _streamAccount.add(mock); - return Future.value(_connectedMock?.left); - } - - @override - Future updatePassword({required String password}) { - final before = DateTime.now().subtract(const Duration(seconds: 10)); - if (_lastSignInTime.isBefore(before)) { - throw UpdatePasswordFailureFirebase('requires-recent-login'); - } - final refresh = DateTime.now(); - final mock = (_connectedMock?.left as AccountModel?) - ?.copyWith(lastSignInTime: refresh); - _connectedMock = _connectedMock?.copyWith(left: mock, right: password); - _registeredMock = _registeredMock?.copyWith(left: mock, right: password); - _streamAccount.add(mock); - return Future.value(_connectedMock?.left); + throw UnimplementedError(); } } diff --git a/packages/wyatt_authentication_bloc/example/lib/core/constants/form_field.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/remote.dart similarity index 78% rename from packages/wyatt_authentication_bloc/example/lib/core/constants/form_field.dart rename to packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/remote.dart index 917131da..e76b675f 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/constants/form_field.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/remote.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -abstract class AppFormField { - static const oldPassword = 'oldPassword'; - static const confirmedPassword = 'confirmedPassword'; -} +export 'authentication_base_data_source.dart'; +export 'authentication_firebase_data_source_impl.dart'; +export 'authentication_mock_data_source_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart index 0077378b..683dd500 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart @@ -1,5 +1,4 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,74 +14,111 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +/// {@template account_model} +/// Account Model to parse Firebase User data +/// {@endtemplate} class AccountModel extends Account { - @override - final String uid; + /// {@macro account_model} + factory AccountModel.fromFirebaseUserCredential( + UserCredential? userCredential, { + required String? accessToken, + }) { + final user = userCredential?.user; + if (user != null) { + final providerId = + (user.providerData.isEmpty) ? '' : user.providerData.first.providerId; + return AccountModel._( + user: user, + id: user.uid, + emailVerified: user.emailVerified, + isAnonymous: user.isAnonymous, + providerId: providerId, + creationTime: user.metadata.creationTime, + lastSignInTime: user.metadata.lastSignInTime, + isNewUser: userCredential?.additionalUserInfo?.isNewUser, + email: user.email, + phoneNumber: user.phoneNumber, + photoURL: user.photoURL, + accessToken: accessToken, + ); + } else { + throw ModelParsingFailureFirebase('null-user', 'User cannot be null'); + } + } - @override - final String? email; + /// {@macro account_model} + factory AccountModel.fromFirebaseUser( + User? user, { + required String? accessToken, + }) { + if (user != null) { + final providerId = + (user.providerData.isEmpty) ? '' : user.providerData.first.providerId; + return AccountModel._( + user: user, + id: user.uid, + emailVerified: user.emailVerified, + isAnonymous: user.isAnonymous, + providerId: providerId, + creationTime: user.metadata.creationTime, + lastSignInTime: user.metadata.lastSignInTime, + isNewUser: false, + email: user.email, + phoneNumber: user.phoneNumber, + photoURL: user.photoURL, + accessToken: accessToken, + ); + } else { + throw ModelParsingFailureFirebase('null-user', 'User cannot be null'); + } + } - @override - final DateTime? creationTime; + /// {@macro account_model} + factory AccountModel.fromSecureStorage({ + required String? id, + required String? email, + required String? accessToken, + }) { + if (id != null && email != null && accessToken != null) { + return AccountModel._( + user: null, + id: id, + emailVerified: false, + isAnonymous: false, + providerId: '', + email: email, + accessToken: accessToken, + ); + } else { + throw Exception( + 'null-id-email-access-token' + 'id, email, and accessToken cannot be null', + ); + } + } - @override - final bool emailVerified; - - @override - final bool isAnonymous; - - @override - final bool? isNewUser; - - @override - final DateTime? lastSignInTime; - - @override - final String? phoneNumber; - - @override - final String? photoURL; - - @override - final String providerId; - - AccountModel({ - required this.uid, - required this.emailVerified, - required this.isAnonymous, - required this.providerId, - this.lastSignInTime, - this.creationTime, - this.isNewUser, - this.email, - this.phoneNumber, - this.photoURL, + const AccountModel._({ + required this.user, + required super.id, + required super.emailVerified, + required super.isAnonymous, + required super.providerId, + super.lastSignInTime, + super.creationTime, + super.isNewUser, + super.email, + super.phoneNumber, + super.photoURL, + super.accessToken, }); - AccountModel copyWith({ - String? uid, - String? email, - DateTime? creationTime, - bool? emailVerified, - bool? isAnonymous, - bool? isNewUser, - DateTime? lastSignInTime, - String? phoneNumber, - String? photoURL, - String? providerId, - }) => - AccountModel( - uid: uid ?? this.uid, - email: email ?? this.email, - creationTime: creationTime ?? this.creationTime, - emailVerified: emailVerified ?? this.emailVerified, - isAnonymous: isAnonymous ?? this.isAnonymous, - isNewUser: isNewUser ?? this.isNewUser, - lastSignInTime: lastSignInTime ?? this.lastSignInTime, - phoneNumber: phoneNumber ?? this.phoneNumber, - photoURL: photoURL ?? this.photoURL, - providerId: providerId ?? this.providerId, - ); + /// The Firebase User + final User? user; + + @override + String? get refreshToken => user?.refreshToken; } diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart deleted file mode 100644 index 22313043..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart +++ /dev/null @@ -1,55 +0,0 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; - -class AccountModelFirebase extends AccountModel { - AccountModelFirebase._({ - required super.uid, - required super.emailVerified, - required super.isAnonymous, - required super.providerId, - super.lastSignInTime, - super.creationTime, - super.isNewUser, - super.email, - super.phoneNumber, - super.photoURL, - }); - - factory AccountModelFirebase.fromFirebaseUser(User? user) { - if (user != null) { - return AccountModelFirebase._( - uid: user.uid, - emailVerified: user.emailVerified, - isAnonymous: user.isAnonymous, - providerId: user.providerData.first.providerId, - creationTime: user.metadata.creationTime, - lastSignInTime: user.metadata.lastSignInTime, - isNewUser: (user.metadata.creationTime != null && - user.metadata.lastSignInTime != null) - ? user.metadata.lastSignInTime! == user.metadata.creationTime! - : null, - email: user.email, - phoneNumber: user.phoneNumber, - photoURL: user.photoURL, - ); - } else { - throw ModelParsingFailureFirebase('null-user', 'User cannot be null!'); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart index 14f991fe..3efbdbc0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,4 +15,3 @@ // along with this program. If not, see . export 'account_model.dart'; -export 'account_wrapper_model.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart index e2687ea8..9b8bc99a 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,101 +14,150 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'dart:async'; - -import 'package:rxdart/rxdart.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; -import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; -import 'package:wyatt_authentication_bloc/src/data/models/account_wrapper_model.dart'; -import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_cache_data_source.dart'; -import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/forms.dart'; +import 'package:wyatt_authentication_bloc/src/domain/domain.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -typedef OnSignUpSuccess = FutureOrResult Function( - AuthenticationRepository repo, - Account? account, - WyattForm form, -); - -typedef OnAuthChange = FutureOrResult Function( - AuthenticationRepository repo, - Account? account, -); - -class AuthenticationRepositoryImpl - extends AuthenticationRepository { +/// {@template authentication_repository_impl} +/// The default implementation of [AuthenticationRepository]. +/// {@endtemplate} +class AuthenticationRepositoryImpl + extends AuthenticationRepository { + /// {@macro authentication_repository_impl} AuthenticationRepositoryImpl({ - required AuthenticationCacheDataSource authenticationCacheDataSource, - required AuthenticationRemoteDataSource authenticationRemoteDataSource, + required this.authenticationRemoteDataSource, + required this.authenticationCacheDataSource, + required this.authenticationSessionDataSource, FormRepository? formRepository, // ignore: strict_raw_type List? extraSignUpInputs, + // ignore: strict_raw_type + List? extraEditAccountInputs, FormInputValidator? customEmailValidator, FormInputValidator? customPasswordValidator, - OnSignUpSuccess? onSignUpSuccess, - OnAuthChange? onAuthChange, - }) : _authenticationLocalDataSource = authenticationCacheDataSource, - _authenticationRemoteDataSource = authenticationRemoteDataSource, - _onSignUpSuccess = onSignUpSuccess, - _onAccountChanges = onAuthChange { + }) { _formRepository = formRepository ?? FormRepositoryImpl(); + if (formRepository != null) { return; } _formRepository ..registerForm( - WyattFormImpl( - [ - FormInput( - AuthFormField.email, - customEmailValidator ?? const Email.pure(), - ), - FormInput( - AuthFormField.password, - customPasswordValidator ?? const Password.pure(), - ) - ], - name: AuthFormName.signInForm, + Forms.buildSignUpForm( + customEmailValidator, + customPasswordValidator, + extraSignUpInputs, ), ) ..registerForm( - WyattFormImpl( - [ - FormInput( - AuthFormField.email, - customEmailValidator ?? const Email.pure(), - ), - FormInput( - AuthFormField.password, - customPasswordValidator ?? const Password.pure(), - ), - ...extraSignUpInputs ?? [] - ], - name: AuthFormName.signUpForm, + Forms.buildSignInForm( + customEmailValidator, + customPasswordValidator, + ), + ) + ..registerForm( + Forms.buildPasswordResetForm(customEmailValidator), + ) + ..registerForm( + Forms.buildEditAccountForm( + customEmailValidator, + customPasswordValidator, + extraEditAccountInputs, ), ); } - final AuthenticationCacheDataSource _authenticationLocalDataSource; - final AuthenticationRemoteDataSource _authenticationRemoteDataSource; + + /// The remote data source used to perform the authentication process. + final AuthenticationRemoteDataSource authenticationRemoteDataSource; + + /// The cache data source used to cache the current account. + final AuthenticationCacheDataSource authenticationCacheDataSource; + + /// The session data source used to manage the current session. + final AuthenticationSessionDataSource authenticationSessionDataSource; late FormRepository _formRepository; - final OnSignUpSuccess? _onSignUpSuccess; - - final OnAuthChange? _onAccountChanges; - final StreamController>> _signUpStream = - StreamController(); - - bool _pause = false; - + /// {@macro form_repo} @override FormRepository get formRepository => _formRepository; + // Cache related methods ==================================================== + + /// {@macro check_cache_account} + @override + Future checkForCachedAccount() async { + final cachedAccount = + await authenticationCacheDataSource.getCachedAccount(); + + if (cachedAccount == null) { + addSession( + const AuthenticationSession( + latestEvent: UnknownAuthenticationEvent(), + ), + ); + return; + } + + addSession( + AuthenticationSession.fromEvent( + SignedInFromCacheEvent(account: cachedAccount), + ), + ); + return; + } + + // Session related methods =================================================== + + /// {@macro add_session} + @override + void addSession(AuthenticationSession session) => + authenticationSessionDataSource.addSession(session); + + /// {@macro session_stream} + @override + Stream> sessionStream() => + authenticationSessionDataSource.sessionStream(); + + /// {@macro current_session} + @override + FutureOrResult> currentSession() => + Result.tryCatchAsync, AppException, + AppException>( + () async { + final session = + await authenticationSessionDataSource.currentSession(); + + return session; + }, + (error) => error, + ); + + // SignUp/SignIn methods ==================================================== + + /// {@macro signup_pwd} + @override + FutureOrResult signUpWithEmailAndPassword({ + required String email, + required String password, + }) => + Result.tryCatchAsync( + () async { + final account = + await authenticationRemoteDataSource.signUpWithEmailAndPassword( + email: email, + password: password, + ); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); + return account; + }, + (error) => error, + ); + + /// {@macro signin_pwd} @override FutureOrResult signInWithEmailAndPassword({ required String email, @@ -117,137 +166,149 @@ class AuthenticationRepositoryImpl Result.tryCatchAsync( () async { final account = - await _authenticationRemoteDataSource.signInWithEmailAndPassword( + await authenticationRemoteDataSource.signInWithEmailAndPassword( email: email, password: password, ); - await _authenticationLocalDataSource.storeAccount(account); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); return account; }, (error) => error, ); + /// {@macro signin_anom} + @override + FutureOrResult signInAnonymously() => + Result.tryCatchAsync( + () async { + final account = + await authenticationRemoteDataSource.signInAnonymously(); + return account; + }, + (error) => error, + ); + + /// {@macro signin_google} + @override + FutureOrResult signInWithGoogle() => + Result.tryCatchAsync( + () async { + final account = + await authenticationRemoteDataSource.signInWithGoogle(); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); + return account; + }, + (error) => error, + ); + + /// {@macro signout} @override FutureOrResult signOut() => Result.tryCatchAsync( () async { - await _authenticationRemoteDataSource.signOut(); - await _authenticationLocalDataSource.destroy(); + await authenticationRemoteDataSource.signOut(); + // Remove the cached account + await authenticationCacheDataSource.removeCachedAccount(); }, (error) => error, ); + // Account management methods =============================================== + + /// {@macro refresh} @override - FutureOrResult signUp({ - required String email, - required String password, - }) => + FutureOrResult refresh() => Result.tryCatchAsync( () async { - _pause = true; - final account = await _authenticationRemoteDataSource.signUp( - email: email, - password: password, - ); - await _authenticationLocalDataSource.storeAccount(account); - if (_onSignUpSuccess.isNotNull) { - final dataResult = await _onSignUpSuccess!.call( - this, - account, - _formRepository.accessForm(AuthFormName.signUpForm).clone(), - ); - await dataResult.foldAsync( - (data) async { - await _authenticationLocalDataSource.storeData(data); - _signUpStream - .add(Future.value(Ok(AccountWrapperModel(account, data)))); - }, - (error) async => error, - ); - } - _pause = false; + final account = await authenticationRemoteDataSource.refresh(); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); return account; }, - (error) { - _pause = false; - return error; - }, - ); - - @override - FutureOrResult destroyCache() => - Result.tryCatchAsync( - _authenticationLocalDataSource.destroy, (error) => error, ); + /// {@macro reauthenticate} @override - FutureOrResult> getCache() => - Result.tryCatchAsync, AppException, AppException>( - _authenticationLocalDataSource.load, - (error) => error, - ); - - @override - FutureOrResult getAccount() => + FutureOrResult reauthenticate() => Result.tryCatchAsync( - _authenticationLocalDataSource.loadAccount, - (error) => error, - ); - - @override - FutureOrResult setAccount( - Account account, - ) => - Result.tryCatchAsync( () async { - await _authenticationLocalDataSource.storeAccount(account); + final account = await authenticationRemoteDataSource.reauthenticate(); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); + return account; }, (error) => error, ); + /// {@macro update_email} @override - FutureOrResult getData() => - Result.tryCatchAsync( - _authenticationLocalDataSource.loadData, - (error) => error, - ); - - @override - FutureOrResult setData( - T? data, - ) => - Result.tryCatchAsync( + FutureOrResult updateEmail({required String email}) => + Result.tryCatchAsync( () async { - await _authenticationLocalDataSource.storeData(data); + final account = + await authenticationRemoteDataSource.updateEmail(email: email); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); + return account; }, (error) => error, ); + /// {@macro update_password} @override - FutureOrResult getIdentityToken() => - Result.tryCatchAsync( - _authenticationRemoteDataSource.getIdentityToken, - (error) => error, - ); - - @override - Stream>> streamAccount() => MergeStream([ - _signUpStream.stream.asBroadcastStream(), - _authenticationRemoteDataSource.streamAccount().map((account) async { - if (_onAccountChanges.isNotNull && !_pause) { - final dataResult = await _onAccountChanges!.call(this, account); - return dataResult.map((data) { - _authenticationLocalDataSource.storeData(data); - return AccountWrapperModel(account, data); - }); - } - return Ok, AppException>( - AccountWrapperModel(account, null), + FutureOrResult updatePassword({required String password}) => + Result.tryCatchAsync( + () async { + final account = await authenticationRemoteDataSource.updatePassword( + password: password, ); - }) - ]); + // Cache the account + await authenticationCacheDataSource.cacheAccount(account); + return account; + }, + (error) => error, + ); + /// {@macro delete} + @override + FutureOrResult delete() => + Result.tryCatchAsync( + () async { + await authenticationRemoteDataSource.delete(); + // Remove the cached account + await authenticationCacheDataSource.removeCachedAccount(); + }, + (error) => error, + ); + + // Email related stuff ====================================================== + + /// {@macro send_email_verification} + @override + FutureOrResult sendEmailVerification() => + Result.tryCatchAsync( + () async { + await authenticationRemoteDataSource.sendEmailVerification(); + }, + (error) => error, + ); + + /// {@macro send_password_reset_email} + @override + FutureOrResult sendPasswordResetEmail({required String email}) => + Result.tryCatchAsync( + () async { + await authenticationRemoteDataSource.sendPasswordResetEmail( + email: email, + ); + }, + (error) => error, + ); + + /// {@macro confirm_password_reset} @override FutureOrResult confirmPasswordReset({ required String code, @@ -255,7 +316,7 @@ class AuthenticationRepositoryImpl }) => Result.tryCatchAsync( () async { - await _authenticationRemoteDataSource.confirmPasswordReset( + await authenticationRemoteDataSource.confirmPasswordReset( code: code, newPassword: newPassword, ); @@ -263,99 +324,15 @@ class AuthenticationRepositoryImpl (error) => error, ); - @override - FutureOrResult sendEmailVerification() => - Result.tryCatchAsync( - () async { - await _authenticationRemoteDataSource.sendEmailVerification(); - }, - (error) => error, - ); - - @override - FutureOrResult sendPasswordResetEmail({required String email}) => - Result.tryCatchAsync( - () async { - await _authenticationRemoteDataSource.sendPasswordResetEmail( - email: email, - ); - }, - (error) => error, - ); - - @override - FutureOrResult signInAnonymously() => - Result.tryCatchAsync( - () async { - final account = - await _authenticationRemoteDataSource.signInAnonymously(); - return account; - }, - (error) => error, - ); - - @override - FutureOrResult signInWithGoogle() => - Result.tryCatchAsync( - () async { - final account = - await _authenticationRemoteDataSource.signInWithGoogle(); - return account; - }, - (error) => error, - ); - + /// {@macro verify_password_reset_code} @override FutureOrResult verifyPasswordResetCode({required String code}) => Result.tryCatchAsync( () async { - final response = await _authenticationRemoteDataSource + final response = await authenticationRemoteDataSource .verifyPasswordResetCode(code: code); return response; }, (error) => error, ); - - @override - FutureOrResult refresh() => - Result.tryCatchAsync( - () async { - await _authenticationRemoteDataSource.refresh(); - }, - (error) => error, - ); - - @override - FutureOrResult reauthenticateWithCredential() => - Result.tryCatchAsync( - () async { - final account = await _authenticationRemoteDataSource - .reauthenticateWithCredential(); - return account; - }, - (error) => error, - ); - - @override - FutureOrResult updateEmail({required String email}) => - Result.tryCatchAsync( - () async { - final account = - await _authenticationRemoteDataSource.updateEmail(email: email); - return account; - }, - (error) => error, - ); - - @override - FutureOrResult updatePassword({required String password}) => - Result.tryCatchAsync( - () async { - final account = await _authenticationRemoteDataSource.updatePassword( - password: password, - ); - return account; - }, - (error) => error, - ); } diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart index d5979688..0081a38c 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart index 11efe02d..843f681b 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,5 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'local/authentication_cache_data_source.dart'; -export 'remote/authentication_remote_data_source.dart'; +export 'local/local.dart'; +export 'remote/remote.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart index c4d357e5..911ec217 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,14 +16,25 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; -abstract class AuthenticationCacheDataSource - extends BaseLocalDataSource { - Future storeAccount(Account? account); - Future storeData(T? data); - Future loadAccount(); - Future loadData(); - Future> load(); - Future destroy(); +/// {@template authentication_cache_data_source} +/// A data source that manages the cache strategy. +/// {@endtemplate} +abstract class AuthenticationCacheDataSource extends BaseLocalDataSource { + /// {@macro authentication_cache_data_source} + const AuthenticationCacheDataSource(); + + /// Returns the cached account if it exists. + Future getCachedAccount(); + + /// Adds the current account to the cache. + /// + /// If an account is already cached, it will be replaced. + Future cacheAccount(Account account); + + /// Removes the current account from the cache. + /// + /// The cache will be empty after this operation. + /// If no account is cached, nothing will happen. + Future removeCachedAccount(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_session_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_session_data_source.dart new file mode 100644 index 00000000..c24d859a --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_session_data_source.dart @@ -0,0 +1,36 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +/// {@template authentication_session_data_source} +/// A data source that manages the current session. +/// {@endtemplate} +abstract class AuthenticationSessionDataSource + extends BaseLocalDataSource { + /// {@macro authentication_session_data_source} + const AuthenticationSessionDataSource(); + + /// Adds a new session to the data source. + void addSession(AuthenticationSession session); + + /// Returns a stream of sessions. + Stream> sessionStream(); + + /// Returns the current session. + Future> currentSession(); +} diff --git a/packages/wyatt_authentication_bloc/example/lib/core/constants/form_name.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/local.dart similarity index 83% rename from packages/wyatt_authentication_bloc/example/lib/core/constants/form_name.dart rename to packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/local.dart index b41b7335..739d4717 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/constants/form_name.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/local.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,6 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -abstract class AppFormName { - static const editProfile = 'editProfile'; -} +export 'authentication_cache_data_source.dart'; +export 'authentication_session_data_source.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart index 8205bd8d..8d9afab5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -17,43 +17,70 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource { - Future signUp({ +/// {@template authentication_remote_data_source} +/// A remote data source for authentication. +/// It is responsible for all the external communication with the authentication +/// providers. +/// {@endtemplate} +abstract class AuthenticationRemoteDataSource + extends BaseRemoteDataSource { + /// {@macro authentication_remote_data_source} + const AuthenticationRemoteDataSource(); + + // SignUp/SignIn methods ==================================================== + + /// Sign up with email and password. + Future signUpWithEmailAndPassword({ required String email, required String password, }); + /// Sign in with email and password. Future signInWithEmailAndPassword({ required String email, required String password, }); + /// Sign in anonymously. + Future signInAnonymously(); + + /// Sign in with Google. + Future signInWithGoogle(); + + /// Sign out. Future signOut(); - Future refresh(); + // Account management methods =============================================== - Stream streamAccount(); + /// Refresh the current account. + Future refresh(); - Future getIdentityToken(); + /// Reauthenticate the current account. + Future reauthenticate(); + /// Update the current account's email. + Future updateEmail({required String email}); + + /// Update the current account's password. + Future updatePassword({required String password}); + + /// Delete the current account. + Future delete(); + + // Email related stuff ====================================================== + + /// Send an email verification. Future sendEmailVerification(); + /// Send a password reset email. Future sendPasswordResetEmail({required String email}); + /// Confirm password reset. Future confirmPasswordReset({ required String code, required String newPassword, }); + /// Verify password reset code. Future verifyPasswordResetCode({required String code}); - - Future signInAnonymously(); - - Future signInWithGoogle(); - - Future updateEmail({required String email}); - - Future updatePassword({required String password}); - - Future reauthenticateWithCredential(); } diff --git a/packages/wyatt_http_client/lib/src/middlewares/access_token_auth_middleware.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/remote.dart similarity index 88% rename from packages/wyatt_http_client/lib/src/middlewares/access_token_auth_middleware.dart rename to packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/remote.dart index 1bb8b149..7d684507 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/access_token_auth_middleware.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/remote.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -13,3 +13,5 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . + +export 'authentication_remote_data_source.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart index 6f4ec438..25af7843 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart index 5723d3a5..c0186496 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -17,67 +17,91 @@ import 'package:equatable/equatable.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -abstract class Account extends Equatable implements Entity { +/// {@template account} +/// Represents a user [Account] in the +/// various identity provisioning systems. +/// {@endtemplate} +class Account extends Equatable implements Entity { + /// {@macro account} + const Account({ + required this.id, + required this.isAnonymous, + required this.emailVerified, + required this.providerId, + this.email, + this.phoneNumber, + this.photoURL, + this.creationTime, + this.lastSignInTime, + this.isNewUser, + this.accessToken, + this.refreshToken, + }); + /// The user's unique ID. - String get uid; + final String id; + + /// Returns whether the user is a anonymous. + final bool isAnonymous; /// The users email address. /// /// Will be `null` if signing in anonymously. - String? get email; + final String? email; /// Returns whether the users email address has been verified. /// /// To send a verification email, see `SendEmailVerification`. - bool get emailVerified; - - /// Returns whether the user is a anonymous. - bool get isAnonymous; - - /// Returns the users account creation time. - /// - /// When this account was created as dictated by the server clock. - DateTime? get creationTime; - - /// When the user last signed in as dictated by the server clock. - DateTime? get lastSignInTime; + final bool emailVerified; /// Returns the users phone number. /// /// This property will be `null` if the user has not signed in or been has /// their phone number linked. - String? get phoneNumber; + final String? phoneNumber; /// Returns a photo URL for the user. /// /// This property will be populated if the user has signed in or been linked /// with a 3rd party OAuth provider (such as Google). - String? get photoURL; + final String? photoURL; - /// The provider ID for the user. - String get providerId; + /// Returns the users account creation time. + /// + /// When this account was created as dictated by the server clock. + final DateTime? creationTime; + + /// When the user last signed in as dictated by the server clock. + final DateTime? lastSignInTime; /// Whether the user account has been recently created. - bool? get isNewUser; + final bool? isNewUser; + + /// The provider ID for the user. + final String providerId; + + /// The user access token + final String? accessToken; + + /// The user refresh token + final String? refreshToken; @override List get props => [ - uid, + id, + isAnonymous, email, emailVerified, - isAnonymous, - creationTime, - lastSignInTime, phoneNumber, photoURL, + creationTime, + lastSignInTime, providerId, isNewUser, + accessToken, + refreshToken, ]; @override - String toString() => 'AccountModel(uid: $uid, email: $email, ' - 'creationTime: $creationTime, emailVerified: $emailVerified, ' - 'isAnonymous: $isAnonymous, isNewUser: $isNewUser, lastSignInTime: ' - '$lastSignInTime, phoneNumber: $phoneNumber, photoURL: $photoURL, ' - 'providerId: $providerId)'; + bool get stringify => true; } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/auth_session.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/auth_session.dart new file mode 100644 index 00000000..bdcbff74 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/auth_session.dart @@ -0,0 +1,69 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:equatable/equatable.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +/// {@template authentication_session} +/// The [AuthenticationSession] object is used to transport and propagate +/// the last event issued by an authentication state change, a user account +/// if connected, and the associated data. +/// {@endtemplate} +class AuthenticationSession extends Equatable { + /// {@macro authentication_session} + const AuthenticationSession({ + required this.latestEvent, + this.account, + this.data, + }); + + /// Creates a new [AuthenticationSession] from an [AuthenticationChangeEvent]. + factory AuthenticationSession.fromEvent( + AuthenticationChangeEvent latestEvent, { + Data? data, + }) { + if (latestEvent is AuthenticatedChangeEvent) { + return AuthenticationSession( + latestEvent: latestEvent, + account: latestEvent.account, + data: data, + ); + } + return AuthenticationSession( + latestEvent: latestEvent, + data: data, + ); + } + + /// The last event issued by an authentication state change. + final AuthenticationChangeEvent latestEvent; + + /// The user account if connected. + final Account? account; + + /// The associated data. + final Data? data; + + @override + List get props => [ + latestEvent, + account, + data, + ]; + + @override + bool? get stringify => true; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authenticated_change_event.dart similarity index 59% rename from packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart rename to packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authenticated_change_event.dart index 0788e03e..fb9487dd 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authenticated_change_event.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,17 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:equatable/equatable.dart'; -import 'package:wyatt_architecture/wyatt_architecture.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +part of 'authentication_change_event.dart'; -abstract class AccountWrapper extends Equatable implements Entity { - Account? get account; - T? get data; +/// {@template authenticated_change_event} +/// Represents every event where user is authenticated. +/// {@endtemplate} +abstract class AuthenticatedChangeEvent extends AuthenticationChangeEvent { + /// {@macro authenticated_change_event} + const AuthenticatedChangeEvent({required this.account}); + + /// The user's account. + final Account account; @override - List get props => [account, data]; - - @override - String toString() => 'AccountWrapper($account, data: $data)'; + List get props => [account]; } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authentication_change_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authentication_change_event.dart new file mode 100644 index 00000000..b32b68b4 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/authentication_change_event.dart @@ -0,0 +1,45 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:equatable/equatable.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +part 'authenticated_change_event.dart'; +part 'deleted_event.dart'; +part 'reauthenticated_event.dart'; +part 'refreshed_event.dart'; +part 'signed_in_event.dart'; +part 'signed_in_from_cache_event.dart'; +part 'signed_out_event.dart'; +part 'signed_up_event.dart'; +part 'unknown_authentication_event.dart'; +part 'updated_event.dart'; + +/// {@template authentication_change_event} +/// Represents an event initiated by a change in +/// the user's authentication status. +/// {@endtemplate} +abstract class AuthenticationChangeEvent extends Equatable implements Entity { + /// {@macro authentication_change_event} + const AuthenticationChangeEvent(); + + @override + List get props => []; + + @override + bool get stringify => true; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/deleted_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/deleted_event.dart new file mode 100644 index 00000000..0ab52ae9 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/deleted_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template deleted_event} +/// When a user deleted his account. +/// {@endtemplate} +class DeletedEvent extends AuthenticationChangeEvent { + /// {@macro deleted_event} + const DeletedEvent(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/reauthenticated_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/reauthenticated_event.dart new file mode 100644 index 00000000..fa7e066a --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/reauthenticated_event.dart @@ -0,0 +1,27 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template reauthenticated_event} +/// When a user re-authenticates (from the logged in state to the +/// logged in state with a different and fresh access +/// token and a different login time) +/// {@endtemplate} +class ReauthenticatedEvent extends AuthenticatedChangeEvent { + /// {@macro reauthenticated_event} + const ReauthenticatedEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/refreshed_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/refreshed_event.dart new file mode 100644 index 00000000..f765c3cc --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/refreshed_event.dart @@ -0,0 +1,26 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template refreshed_event} +/// When a user access token is refreshed (from the logged in state to the +/// logged in state with a different access token) +/// {@endtemplate} +class RefreshedEvent extends AuthenticatedChangeEvent { + /// {@macro refreshed_event} + const RefreshedEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_event.dart new file mode 100644 index 00000000..17b2ae3e --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template signed_in_event} +/// When a user authenticates (from not logged in to logged in). +/// {@endtemplate} +class SignedInEvent extends AuthenticatedChangeEvent { + /// {@macro signed_in_event} + const SignedInEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_from_cache_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_from_cache_event.dart new file mode 100644 index 00000000..01bf868d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_in_from_cache_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template signed_in_from_cache_event} +/// When a user authenticates automatically (from not logged in to logged in). +/// {@endtemplate} +class SignedInFromCacheEvent extends AuthenticatedChangeEvent { + /// {@macro signed_in_from_cache_event} + const SignedInFromCacheEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_out_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_out_event.dart new file mode 100644 index 00000000..dc4ea4cd --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_out_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template signed_out_event} +/// When a user logs out. +/// {@endtemplate} +class SignedOutEvent extends AuthenticationChangeEvent { + /// {@macro signed_out_event} + const SignedOutEvent(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_up_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_up_event.dart new file mode 100644 index 00000000..f95f7e5e --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/signed_up_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template signed_up_event} +/// When a user creates an account. +/// {@endtemplate} +class SignedUpEvent extends AuthenticatedChangeEvent { + /// {@macro signed_up_event} + const SignedUpEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/unknown_authentication_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/unknown_authentication_event.dart new file mode 100644 index 00000000..287b53a0 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/unknown_authentication_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template unknown_authentication_event} +/// When a user's login status is unknown. +/// {@endtemplate} +class UnknownAuthenticationEvent extends AuthenticationChangeEvent { + /// {@macro unknown_authentication_event} + const UnknownAuthenticationEvent(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/updated_event.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/updated_event.dart new file mode 100644 index 00000000..2178a56e --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/authentication_change_event/updated_event.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'authentication_change_event.dart'; + +/// {@template updated_event} +/// When the user's account has been updated. +/// {@endtemplate} +class UpdatedEvent extends AuthenticatedChangeEvent { + /// {@macro updated_event} + const UpdatedEvent({required super.account}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart index e9a858fe..a1afb54e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,4 +15,5 @@ // along with this program. If not, see . export 'account.dart'; -export 'account_wrapper.dart'; +export 'auth_session.dart'; +export 'authentication_change_event/authentication_change_event.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart index 027c7525..a4f8769c 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,13 +16,47 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -abstract class AuthenticationRepository extends BaseRepository { +/// {@template auth_repo} +/// Authentication repository interface. +/// {@endtemplate} +abstract class AuthenticationRepository extends BaseRepository { + /// {@template form_repo} + /// Form repository used in different authentication cubits/blocs + /// {@endtemplate} FormRepository get formRepository; - /// {@template signup} + // Cache related methods ==================================================== + + /// {@template check_cache_account} + /// Checks if there is a cached account. + /// And if there is, it will sign in the user automatically by + /// emitting an event. + /// {@endtemplate} + Future checkForCachedAccount(); + + // Session related methods =================================================== + + /// {@template add_session} + /// Add a new authentication event. + /// {@endtemplate} + void addSession(AuthenticationSession session); + + /// {@template session_stream} + /// Authentication state change event stream. + /// {@endtemplate} + Stream> sessionStream(); + + /// {@template current_session} + /// Latest session issued by the session stream. + /// {@endtemplate} + FutureOrResult> currentSession(); + + // SignUp/SignIn methods ==================================================== + + /// {@template signup_pwd} /// Creates a new user with the provided [email] and [password]. /// /// Returns the newly created user's unique identifier. @@ -30,11 +64,89 @@ abstract class AuthenticationRepository extends BaseRepository { /// Throws a SignUpWithEmailAndPasswordFailureInterface if /// an exception occurs. /// {@endtemplate} - FutureOrResult signUp({ + FutureOrResult signUpWithEmailAndPassword({ required String email, required String password, }); + /// {@template signin_pwd} + /// Signs in with the provided [email] and [password]. + /// + /// Throws a SignInWithEmailAndPasswordFailureInterface if + /// an exception occurs. + /// {@endtemplate} + FutureOrResult signInWithEmailAndPassword({ + required String email, + required String password, + }); + + /// {@template signin_anom} + /// Sign in anonymously. + /// + /// Throws a SignInAnonymouslyFailureInterface if an exception occurs. + /// {@endtemplate} + FutureOrResult signInAnonymously(); + + /// {@template signin_google} + /// Starts the Sign In with Google Flow. + /// + /// Throws a SignInWithGoogleFailureInterface if an exception occurs. + /// {@endtemplate} + FutureOrResult signInWithGoogle(); + + /// {@template signout} + /// Signs out the current user. + /// It also clears the cache and the associated data. + /// {@endtemplate} + FutureOrResult signOut(); + + // Account management methods =============================================== + + /// {@template refresh} + /// Refreshes the current user, if signed in. + /// {@endtemplate} + FutureOrResult refresh(); + + /// {@template reauthenticate} + /// Some security-sensitive actions—such as deleting an account, + /// setting a primary email address, and changing a password—require that + /// the user has recently signed in. + /// + /// Throws a ReauthenticateFailureInterface if + /// an exception occurs. + /// {@endtemplate} + FutureOrResult reauthenticate(); + + /// {@template update_email} + /// Update or add [email]. + /// + /// Throws a UpdateEmailFailureInterface if + /// an exception occurs. + /// {@endtemplate} + FutureOrResult updateEmail({ + required String email, + }); + + /// {@template update_password} + /// Update or add [password]. + /// + /// Throws a UpdatePasswordFailureInterface if + /// an exception occurs. + /// {@endtemplate} + FutureOrResult updatePassword({ + required String password, + }); + + /// {@template delete} + /// Delete account. + /// + /// Throws a DeleteAccountFailureInterface if + /// an exception occurs. + /// {@endtemplate} + FutureOrResult delete(); + + // Email related stuff ====================================================== + /// {@template send_email_verification} /// Sends verification email to the account email. /// @@ -65,90 +177,4 @@ abstract class AuthenticationRepository extends BaseRepository { /// Throws a VerifyPasswordResetCodeFailureInterface if an exception occurs. /// {@endtemplate} FutureOrResult verifyPasswordResetCode({required String code}); - - /// {@template signin_anom} - /// Sign in anonymously. - /// - /// Throws a SignInAnonymouslyFailureInterface if an exception occurs. - /// {@endtemplate} - FutureOrResult signInAnonymously(); - - /// {@template signin_google} - /// Starts the Sign In with Google Flow. - /// - /// Throws a SignInWithGoogleFailureInterface if an exception occurs. - /// {@endtemplate} - FutureOrResult signInWithGoogle(); - - /// {@template signin_pwd} - /// Signs in with the provided [email] and [password]. - /// - /// Throws a SignInWithEmailAndPasswordFailureInterface if - /// an exception occurs. - /// {@endtemplate} - FutureOrResult signInWithEmailAndPassword({ - required String email, - required String password, - }); - - /// {@template update_email} - /// Update or add [email]. - /// - /// Throws a UpdateEmailFailureInterface if - /// an exception occurs. - /// {@endtemplate} - FutureOrResult updateEmail({ - required String email, - }); - - /// {@template update_password} - /// Update or add [password]. - /// - /// Throws a UpdatePasswordFailureInterface if - /// an exception occurs. - /// {@endtemplate} - FutureOrResult updatePassword({ - required String password, - }); - - /// {@template reauthenticate} - /// Some security-sensitive actions—such as deleting an account, - /// setting a primary email address, and changing a password—require that - /// the user has recently signed in. - /// - /// Throws a ReauthenticateFailureInterface if - /// an exception occurs. - /// {@endtemplate} - FutureOrResult reauthenticateWithCredential(); - - /// {@template signout} - /// Signs out the current user. - /// It also clears the cache and the associated data. - /// {@endtemplate} - FutureOrResult signOut(); - - /// {@template refresh} - /// Refreshes the current user, if signed in. - /// {@endtemplate} - FutureOrResult refresh(); - - /// {@template stream_account} - /// Stream of [AccountWrapper] which will emit the current account when - /// the authentication state changes. - /// - /// Emits [AccountWrapper] with null [Account] if the user is not - /// authenticated. - /// {@endtemplate} - Stream>> streamAccount(); - - FutureOrResult getIdentityToken(); - - FutureOrResult getAccount(); - FutureOrResult setAccount(Account account); - - FutureOrResult getData(); - FutureOrResult setData(T? data); - - FutureOrResult> getCache(); - FutureOrResult destroyCache(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart index 8ff4eae1..8565338e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/authentication.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/authentication.dart index 95e85224..478b8ad0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/authentication.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/authentication.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart index 4a19e6a9..46eb0a57 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -17,10 +17,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart'; -class AuthenticationBuilder extends StatelessWidget { +/// {@template authentication_builder} +/// A widget that builds itself based on the current authentication state. +/// {@endtemplate} +class AuthenticationBuilder extends StatelessWidget { + /// {@macro authentication_builder} const AuthenticationBuilder({ required this.authenticated, required this.unauthenticated, @@ -28,20 +32,25 @@ class AuthenticationBuilder extends StatelessWidget { super.key, }); + /// Widget to show when the user is authenticated. final Widget Function( BuildContext context, - AccountWrapper accountWrapper, + AuthenticationSession session, ) authenticated; + + /// Widget to show when the user is unauthenticated. final Widget Function(BuildContext context) unauthenticated; + + /// Widget to show when the authentication status is unknown. final Widget Function(BuildContext context) unknown; @override Widget build(BuildContext context) => - BlocBuilder, AuthenticationState>( + BlocBuilder, AuthenticationState>( builder: (context, state) { if (state.status == AuthenticationStatus.authenticated) { - if (state.accountWrapper != null) { - return authenticated(context, state.accountWrapper!); + if (state.session != null) { + return authenticated(context, state.session!); } else { return unauthenticated(context); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart index eab1ffbb..e5abf6ec 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -18,58 +18,166 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/entities.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'authentication_state.dart'; -class AuthenticationCubit extends Cubit> { +/// {@template authentication_cubit} +/// Abstract authentication cubit class needs to be implemented in application. +/// +/// This cubit is in charge of managing the global authentication state of +/// the application. +/// +/// Its here you can override every callbacks and add your custom logic. +/// {@endtemplate} +abstract class AuthenticationCubit + extends Cubit> { + /// {@macro authentication_cubit} AuthenticationCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super(const AuthenticationState.unknown()) { - _listenForAuthenticationChanges(); + required this.authenticationRepository, + }) : super(const AuthenticationState.unknown()) { + _init(); + } + + /// The authentication repository. + final AuthenticationRepository authenticationRepository; + + /// The latest session. + AuthenticationSession? _latestSession; + + /// Method that is called when the cubit is initialized. + Future _init() async { + /// Setup listeners. + _listenForAuthenticationChanges(); + + /// Check if there is a cached account. + await authenticationRepository.checkForCachedAccount(); } - final AuthenticationRepository _authenticationRepository; void _listenForAuthenticationChanges() { - _authenticationRepository.streamAccount().listen((accountFutureResult) { - accountFutureResult.fold( - (value) { - if (value.account.isNotNull) { - emit(AuthenticationState.authenticated(value)); - return; - } - _authenticationRepository.destroyCache(); - emit(AuthenticationState.unauthenticated()); - return; - }, - (error) { - _authenticationRepository.destroyCache(); - emit(AuthenticationState.unauthenticated()); - return; - }, - ); + authenticationRepository.sessionStream().asyncMap((session) async { + final event = session.latestEvent; + + /// If the session is signed in from cache. + if (event is SignedInFromCacheEvent) { + /// Call the custom routine. + final customRoutineResult = await onSignInFromCache(session); + + if (customRoutineResult.isOk) { + final account = event.account; + final sessionData = customRoutineResult.ok; + + final signedInSession = AuthenticationSession.fromEvent( + SignedInFromCacheEvent(account: account), + data: sessionData, + ); + + return signedInSession; + } + } + return session; + }).listen((session) async { + /// Save the latest session. + _latestSession = session; + + /// If there is an account: emit authenticated state. + if (session.account != null) { + emit(AuthenticationState.authenticated(session)); + return; + } + + /// If there is no account: emit unauthenticated state. + emit(AuthenticationState.unauthenticated()); + + return; }); } - /// If authenticated, re-emits state with data freshly loaded from cache. - FutureOr reloadCache() async { - if (state.status == AuthenticationStatus.authenticated) { - final data = await _authenticationRepository.getCache(); - emit( - data.fold( - AuthenticationState.authenticated, - (error) => state, + /// {@macro refresh} + FutureOr refresh() async => CustomRoutine( + routine: authenticationRepository.refresh, + attachedLogic: onRefresh, + onError: addError, + onSuccess: (result, data) => authenticationRepository.addSession( + AuthenticationSession.fromEvent( + RefreshedEvent(account: result), + data: data, + ), ), - ); - } - } + ).call(); - FutureOr signOut() { - // TODO(hpcl): maybe force unauthenticated by emitting an event - _authenticationRepository.signOut(); - } + /// {@macro reauthenticate} + FutureOr reauthenticate() async => CustomRoutine( + routine: authenticationRepository.reauthenticate, + attachedLogic: onReauthenticate, + onError: addError, + onSuccess: (result, data) => authenticationRepository.addSession( + AuthenticationSession.fromEvent( + ReauthenticatedEvent(account: result), + data: data, + ), + ), + ).call(); + + /// {@macro signout} + FutureOr signOut() async => CustomRoutine( + routine: authenticationRepository.signOut, + attachedLogic: (routineResult) => onSignOut(), + onError: addError, + onSuccess: (result, data) => authenticationRepository.addSession( + const AuthenticationSession( + latestEvent: SignedOutEvent(), + ), + ), + ).call(); + + /// {@macro delete} + FutureOr delete() async => CustomRoutine( + routine: authenticationRepository.delete, + attachedLogic: (routineResult) => onDelete(), + onError: addError, + onSuccess: (result, data) => authenticationRepository.addSession( + const AuthenticationSession( + latestEvent: DeletedEvent(), + ), + ), + ).call(); + + /// Returns latest session. + /// + /// Contains latest event and latest session data (account + extra data) + AuthenticationSession? currentSession() => _latestSession; + + /// This callback is triggered when the user is automaticcaly logged in from + /// the cache. + /// + /// For example: when the user is sign in from the Firebase cache. + FutureOrResult onSignInFromCache(AuthenticationSession session); + + /// This callback is triggered when the account is refreshed. + /// + /// For example: when the access token is refreshed. + FutureOrResult onRefresh(Result result); + + /// This callback is triggered when the account is re-authenticated + /// + /// For example: when the user is logged in and sign in + /// from an another provider + FutureOrResult onReauthenticate(Result result); + + /// This callback is triggered when the user is logged out. + /// + /// For example: when the user clicks on the logout button. + FutureOrResult onSignOut(); + + /// This callback is triggered when the current account is deleted from + /// the remote. + /// + /// For example: when the user wants to delete his account from Firebase + FutureOrResult onDelete(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart index a5733bf2..8a51d674 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,27 +16,37 @@ part of 'authentication_cubit.dart'; -class AuthenticationState extends Equatable { - const AuthenticationState.unauthenticated() - : this._(status: AuthenticationStatus.unauthenticated); +/// {@template authentication_status} +/// The status of the authentication cubit. +/// {@endtemplate} +class AuthenticationState extends Equatable { + /// {@macro authentication_status} + const AuthenticationState._(this.status, this.session); - const AuthenticationState.authenticated(AccountWrapper accountWrapper) + /// The user is not authenticated. + const AuthenticationState.unauthenticated() + : this._(AuthenticationStatus.unauthenticated, null); + + /// The user is authenticated. + const AuthenticationState.authenticated(AuthenticationSession session) : this._( - status: AuthenticationStatus.authenticated, - accountWrapper: accountWrapper, + AuthenticationStatus.authenticated, + session, ); + /// The user's authentication status is unknown. const AuthenticationState.unknown() - : this._(status: AuthenticationStatus.unknown); + : this._(AuthenticationStatus.unknown, null); - const AuthenticationState._({required this.status, this.accountWrapper}); + /// The status of the authentication cubit. final AuthenticationStatus status; - final AccountWrapper? accountWrapper; + + /// The session of the authentication cubit. + final AuthenticationSession? session; @override - List get props => [status, accountWrapper]; + List get props => [status, session]; @override - String toString() => - 'AuthenticationState(status: $status, accountWrapper: $accountWrapper)'; + bool? get stringify => true; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart new file mode 100644 index 00000000..119e16fd --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/base_edit_account_cubit.dart @@ -0,0 +1,105 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'edit_account_cubit.dart'; + +/// {@template edit_account_cubit} +/// Abstract edit account cubit useful for implementing a cubit with fine +/// granularity by adding only the required mixins. +/// {@endtemplate} +abstract class BaseEditAccountCubit + extends FormDataCubit { + /// {@macro edit_account_cubit} + BaseEditAccountCubit({ + required this.authenticationRepository, + }) : super( + EditAccountState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signInForm), + ), + ); + + /// The authentication repository. + final AuthenticationRepository authenticationRepository; + FormRepository get formRepository => authenticationRepository.formRepository; + + @override + String get formName => AuthFormName.signInForm; + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = formRepository.accessForm(formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + formRepository.updateForm(form); + } catch (e) { + rethrow; + } + + emit( + EditAccountState(form: form, status: form.validate()), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + formRepository.updateForm(form); + emit( + EditAccountState(form: form, status: form.validate()), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + formRepository.updateForm(newForm); + + emit( + EditAccountState(form: newForm, status: newForm.validate()), + ); + } + + @override + FutureOr validate() { + final WyattForm form = formRepository.accessForm(formName); + emit( + EditAccountState(form: form, status: form.validate()), + ); + } + + @override + FutureOr submit() async { + final WyattForm form = formRepository.accessForm(formName); + const error = '`submit()` is not implemented for BaseEditAccountCubit, ' + 'please use `updateEmail()` or `updatePassword()`.'; + emit( + EditAccountState( + form: form, + errorMessage: error, + status: FormStatus.submissionFailure, + ), + ); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart new file mode 100644 index 00000000..abc378cc --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_cubit.dart @@ -0,0 +1,54 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_authentication_bloc/src/features/edit_account/edit_account.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +part 'base_edit_account_cubit.dart'; +part 'edit_account_state.dart'; + +/// {@template edit_account_cubit} +/// Fully featured edit account cubit. +/// +/// Sufficient in most cases. (Where fine granularity is not required.) +/// {@endtemplate} +class EditAccountCubit extends BaseEditAccountCubit + with UpdateEmail, UpdatePassword { + /// {@macro edit_account_cubit} + EditAccountCubit({required super.authenticationRepository}); + + @override + FutureOrResult onEmailUpdated( + Result result, + WyattForm form, + ) => + const Ok(null); + + @override + FutureOrResult onPasswordUpdated( + Result result, + WyattForm form, + ) => + const Ok(null); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart new file mode 100644 index 00000000..d7dd5032 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/edit_account_state.dart @@ -0,0 +1,55 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'edit_account_cubit.dart'; + +/// {@template edit_account_state} +/// Edit account cubit state to manage the form. +/// {@endtemplate} +class EditAccountState extends FormDataState { + /// {@macro edit_account_state} + const EditAccountState({ + required super.form, + super.status = FormStatus.pure, + super.errorMessage, + }); + + /// Email validator of the form + FormInputValidator get email => + form.validatorOf(AuthFormField.email); + + /// Password validator of the form + FormInputValidator get password => + form.validatorOf(AuthFormField.password); + + EditAccountState copyWith({ + WyattForm? form, + FormStatus? status, + String? errorMessage, + }) => + EditAccountState( + form: form ?? this.form, + status: status ?? this.status, + errorMessage: errorMessage ?? this.errorMessage, + ); + + @override + List get props => [email, password, status]; + + @override + String toString() => 'EditAccountState(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_email.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_email.dart new file mode 100644 index 00000000..c755838f --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_email.dart @@ -0,0 +1,128 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/domain.dart'; +import 'package:wyatt_authentication_bloc/src/features/edit_account/cubit/edit_account_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Edit account mixin. +/// +/// Allows the user to edit his email +/// +/// Gives access to the `updateEmail` method and +/// `onEmailUpdated` callback. +mixin UpdateEmail on BaseEditAccountCubit { + /// This callback is triggered when user updates his email + FutureOrResult onEmailUpdated( + Result result, + WyattForm form, + ); + + void emailChanged(String value) { + final emailValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.email) + .runtimeType; + assert( + emailValidatorType == Email, + 'Use emailCustomChanged(...) with validator $emailValidatorType', + ); + + final Email email = Email.dirty(value); + dataChanged(AuthFormField.email, email); + } + + /// Same as [emailChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void emailCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.email, validator); + } + + /// {@macro update_email} + FutureOr updateEmail() async { + if (state.status.isSubmissionInProgress) { + return; + } + + if (!state.status.isValidated) { + return; + } + + final form = formRepository.accessForm(formName); + emit( + EditAccountState( + form: form, + status: FormStatus.submissionInProgress, + ), + ); + + final email = form.valueOf(AuthFormField.email); + + if (email.isNullOrEmpty) { + emit( + EditAccountState( + form: form, + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + + return CustomRoutine( + routine: () => authenticationRepository.updateEmail( + email: email!, + ), + attachedLogic: (routineResult) => onEmailUpdated( + routineResult, + form, + ), + onError: (error) { + emit( + EditAccountState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + UpdatedEvent(account: account), + data: data, + ), + ); + emit( + EditAccountState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_password.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_password.dart new file mode 100644 index 00000000..31dcb20d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/cubit/mixin/edit_password.dart @@ -0,0 +1,127 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/domain.dart'; +import 'package:wyatt_authentication_bloc/src/features/edit_account/cubit/edit_account_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Edit account mixin. +/// +/// Allows the user to edit his password +/// +/// Gives access to the `updatePassword` method and +/// `onPasswordUpdated` callback. +mixin UpdatePassword on BaseEditAccountCubit { + /// This callback is triggered when a user edits his password. + FutureOrResult onPasswordUpdated( + Result result, + WyattForm form, + ); + + void passwordChanged(String value) { + final passwordValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.password) + .runtimeType; + assert( + passwordValidatorType == Password, + 'Use passwordCustomChanged(...) with validator $passwordValidatorType', + ); + final Password password = Password.dirty(value); + dataChanged(AuthFormField.password, password); + } + + /// Same as [passwordChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void passwordCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.password, validator); + } + + /// {@macro update_password} + FutureOr updatePassword() async { + if (state.status.isSubmissionInProgress) { + return; + } + + if (!state.status.isValidated) { + return; + } + + final form = formRepository.accessForm(formName); + emit( + EditAccountState( + form: form, + status: FormStatus.submissionInProgress, + ), + ); + + final password = form.valueOf(AuthFormField.password); + + if (password.isNullOrEmpty) { + emit( + EditAccountState( + form: form, + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + + return CustomRoutine( + routine: () => authenticationRepository.updatePassword( + password: password!, + ), + attachedLogic: (routineResult) => onPasswordUpdated( + routineResult, + form, + ), + onError: (error) { + emit( + EditAccountState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + UpdatedEvent(account: account), + data: data, + ), + ); + emit( + EditAccountState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/edit_account.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/edit_account.dart new file mode 100644 index 00000000..1040179f --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/edit_account.dart @@ -0,0 +1,20 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'cubit/edit_account_cubit.dart'; +export 'cubit/mixin/edit_email.dart'; +export 'cubit/mixin/edit_password.dart'; +export 'listener/edit_account_listener.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/edit_account/listener/edit_account_listener.dart b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/listener/edit_account_listener.dart new file mode 100644 index 00000000..9adcb5ec --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/edit_account/listener/edit_account_listener.dart @@ -0,0 +1,82 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_authentication_bloc/src/features/edit_account/cubit/edit_account_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +/// {@template edit_account_listener} +/// Widget that listens and builds a child based on the state of +/// the edit account cubit +/// {@endtemplate} +class EditAccountListener extends StatelessWidget { + /// {@macro edit_account_listener} + const EditAccountListener({ + required this.child, + this.onProgress, + this.onSuccess, + this.onError, + this.customBuilder, + super.key, + }); + + /// Callback to show when the edit account is in progress + final void Function(BuildContext context)? onProgress; + + /// Callback to show when the edit account is successful + final void Function(BuildContext context)? onSuccess; + + /// Callback to show when the edit account is unsuccessful + final void Function( + BuildContext context, + FormStatus status, + String? errorMessage, + )? onError; + + /// Custom builder to show when the edit account is in progress, successful, + /// or unsuccessful + final void Function(BuildContext context, EditAccountState state)? + customBuilder; + + /// Child of the widget + final Widget child; + + @override + Widget build(BuildContext context) => + BlocListener, EditAccountState>( + listener: (context, state) { + if (customBuilder != null) { + return customBuilder!(context, state); + } + + if (onSuccess != null && + state.status == FormStatus.submissionSuccess) { + return onSuccess!(context); + } + if (onProgress != null && + state.status == FormStatus.submissionInProgress) { + return onProgress!(context); + } + if (onError != null && + (state.status == FormStatus.submissionCanceled || + state.status == FormStatus.submissionFailure)) { + return onError!(context, state.status, state.errorMessage); + } + }, + child: child, + ); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/builder/email_verification_builder.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/builder/email_verification_builder.dart index 2bb77e9c..c030260d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/builder/email_verification_builder.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/builder/email_verification_builder.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -19,7 +19,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/src/features/email_verification/cubit/email_verification_cubit.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +/// {@template email_verification_builder} +/// A widget that builds itself based on the latest [EmailVerificationState]. +/// {@endtemplate} class EmailVerificationBuilder extends StatelessWidget { + /// {@macro email_verification_builder} const EmailVerificationBuilder({ required this.verified, required this.notVerified, @@ -28,14 +32,21 @@ class EmailVerificationBuilder extends StatelessWidget { super.key, }); + /// Widget to show when the email is verified final Widget Function(BuildContext context) verified; + + /// Widget to show when the email is not verified final Widget Function(BuildContext context) notVerified; + + /// Widget to show when the email verification is unsuccessful final Widget Function( BuildContext context, FormStatus status, String? errorMessage, ) onError; + /// Custom builder to show when the email is verified, not verified, or + /// unsuccessful final Widget Function(BuildContext context, EmailVerificationState)? customBuilder; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart index 132dafd2..92227e52 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -23,20 +23,26 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; part 'email_verification_state.dart'; -class EmailVerificationCubit extends Cubit { +/// {@template email_verification_cubit} +/// Cubit for sending email verification. +/// {@endtemplate} +class EmailVerificationCubit extends Cubit { + /// {@macro email_verification_cubit} EmailVerificationCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super(const EmailVerificationState()); - final AuthenticationRepository _authenticationRepository; + required this.authenticationRepository, + }) : super(const EmailVerificationState()); + + /// The [AuthenticationRepository] used to send email verification. + final AuthenticationRepository authenticationRepository; FutureOr sendEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); - final response = await _authenticationRepository.sendEmailVerification(); + emit(const EmailVerificationState(status: FormStatus.submissionInProgress)); + final response = await authenticationRepository.sendEmailVerification(); emit( response.fold( - (value) => state.copyWith(status: FormStatus.submissionSuccess), - (error) => state.copyWith( + (value) => + const EmailVerificationState(status: FormStatus.submissionSuccess), + (error) => EmailVerificationState( errorMessage: error.message, status: FormStatus.submissionFailure, ), @@ -45,9 +51,9 @@ class EmailVerificationCubit extends Cubit { } FutureOr checkEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); + emit(const EmailVerificationState(status: FormStatus.submissionInProgress)); - final refresh = await _authenticationRepository.refresh(); + final refresh = await authenticationRepository.refresh(); if (refresh.isErr) { final refreshError = refresh.err!; emit( @@ -59,18 +65,20 @@ class EmailVerificationCubit extends Cubit { return; } - final currentAccount = await _authenticationRepository.getAccount(); - emit( - currentAccount.fold( - (value) => state.copyWith( - isVerified: value.emailVerified, + final session = await authenticationRepository.currentSession(); + final currentAccount = session.ok?.account; + if (currentAccount != null) { + emit( + EmailVerificationState( + isVerified: currentAccount.emailVerified, status: FormStatus.submissionSuccess, ), - (error) => EmailVerificationState( - errorMessage: error.message, - status: FormStatus.submissionFailure, - ), - ), - ); + ); + } else { + const EmailVerificationState( + errorMessage: 'No current session', + status: FormStatus.submissionFailure, + ); + } } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart index 5f9382ac..22ac24c7 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart @@ -1,5 +1,4 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -17,17 +16,26 @@ part of 'email_verification_cubit.dart'; +/// {@template email_verification_state} +/// The state of the [EmailVerificationCubit]. +/// {@endtemplate} class EmailVerificationState extends Equatable { - final FormStatus status; - final bool isVerified; - final String? errorMessage; - + /// {@macro email_verification_state} const EmailVerificationState({ this.isVerified = false, this.status = FormStatus.pure, this.errorMessage, }); + /// The status of the form. + final FormStatus status; + + /// Whether the email is verified. + final bool isVerified; + + /// The error message if any. + final String? errorMessage; + EmailVerificationState copyWith({ FormStatus? status, bool? isVerified, diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart index 5624d94e..13ff15c5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/features/features.dart b/packages/wyatt_authentication_bloc/lib/src/features/features.dart index bd39a7f6..cbdaf015 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/features.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/features.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -15,6 +15,7 @@ // along with this program. If not, see . export 'authentication/authentication.dart'; +export 'edit_account/edit_account.dart'; export 'email_verification/email_verification.dart'; export 'password_reset/password_reset.dart'; export 'sign_in/sign_in.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart index 9ecfe309..969528e3 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -24,38 +24,37 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'password_reset_state.dart'; +/// {@template password_reset_cubit} +/// Cubit that allows user to reset his password +/// {@endtemplate} class PasswordResetCubit extends FormDataCubit { + /// {@macro password_reset_cubit} PasswordResetCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super( + required this.authenticationRepository, + }) : super( PasswordResetState( form: authenticationRepository.formRepository .accessForm(AuthFormName.passwordResetForm), ), ); - final AuthenticationRepository _authenticationRepository; - FormRepository get _formRepository => - _authenticationRepository.formRepository; + + /// The repository that handles the authentication + final AuthenticationRepository authenticationRepository; + FormRepository get formRepository => authenticationRepository.formRepository; @override String get formName => AuthFormName.passwordResetForm; - void emailChanged(String value) { - final Email email = Email.dirty(value); - dataChanged(AuthFormField.email, email); - } - @override FutureOr dataChanged( String key, FormInputValidator dirtyValue, ) { - final form = _formRepository.accessForm(formName).clone(); + final form = formRepository.accessForm(formName).clone(); try { form.updateValidator(key, dirtyValue); - _formRepository.updateForm(form); + formRepository.updateForm(form); } catch (e) { rethrow; } @@ -68,12 +67,39 @@ class PasswordResetCubit extends FormDataCubit { @override FutureOr reset() { final form = state.form.reset(); - _formRepository.updateForm(form); + formRepository.updateForm(form); emit( state.copyWith(form: form, status: form.validate()), ); } + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + formRepository.updateForm(newForm); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: formRepository.accessForm(formName).validate(), + ), + ); + } + + /// Sends a password reset email to the user @override FutureOr submit() async { if (!state.status.isValidated) { @@ -82,7 +108,7 @@ class PasswordResetCubit extends FormDataCubit { emit(state.copyWith(status: FormStatus.submissionInProgress)); - final form = _formRepository.accessForm(formName); + final form = formRepository.accessForm(formName); final email = form.valueOf(AuthFormField.email); if (email.isNullOrEmpty) { @@ -94,7 +120,7 @@ class PasswordResetCubit extends FormDataCubit { ); } - final response = await _authenticationRepository.sendPasswordResetEmail( + final response = await authenticationRepository.sendPasswordResetEmail( email: email!, ); @@ -109,29 +135,29 @@ class PasswordResetCubit extends FormDataCubit { ); } - @override - FutureOr update( - WyattForm form, { - SetOperation operation = SetOperation.replace, - }) { - final WyattForm current = _formRepository.accessForm(formName).clone(); - final WyattForm newForm = operation.operation.call(current, form); - _formRepository.updateForm(newForm); - - emit( - state.copyWith( - form: newForm, - status: newForm.validate(), - ), + void emailChanged(String value) { + final emailValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.email) + .runtimeType; + assert( + emailValidatorType == Email, + 'Use emailCustomChanged(...) with validator $emailValidatorType', ); + + final Email email = Email.dirty(value); + dataChanged(AuthFormField.email, email); } - @override - FutureOr validate() { - emit( - state.copyWith( - status: _formRepository.accessForm(formName).validate(), - ), - ); + /// Same as [emailChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void emailCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.email, validator); } + + // TODO(wyatt): create base_password_reset_cubit and create mixins } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart index 5c5205dd..eafbf6b6 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,12 +16,18 @@ part of 'password_reset_cubit.dart'; +/// {@template password_reset_state} +/// The state of the [PasswordResetCubit]. +/// {@endtemplate} class PasswordResetState extends FormDataState { + /// {@macro password_reset_state} const PasswordResetState({ required super.form, super.status = FormStatus.pure, super.errorMessage, }); + + /// The email validator of the form. Email get email => form.validatorOf(AuthFormField.email); PasswordResetState copyWith({ diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart index 43919e02..f9039274 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/base_sign_in_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/base_sign_in_cubit.dart new file mode 100644 index 00000000..3d59bee5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/base_sign_in_cubit.dart @@ -0,0 +1,104 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'sign_in_cubit.dart'; + +/// {@template sign_in_cubit} +/// Abstract sign in cubit useful for implementing a cubit with fine +/// granularity by adding only the required mixins. +/// {@endtemplate} +abstract class BaseSignInCubit extends FormDataCubit { + /// {@macro sign_in_cubit} + BaseSignInCubit({ + required this.authenticationRepository, + }) : super( + SignInState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signInForm), + ), + ); + + /// The authentication repository. + final AuthenticationRepository authenticationRepository; + FormRepository get formRepository => authenticationRepository.formRepository; + + @override + String get formName => AuthFormName.signInForm; + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = formRepository.accessForm(formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + formRepository.updateForm(form); + } catch (e) { + rethrow; + } + + emit( + SignInState(form: form, status: form.validate()), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + formRepository.updateForm(form); + emit( + SignInState(form: form, status: form.validate()), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + formRepository.updateForm(newForm); + + emit( + SignInState(form: newForm, status: newForm.validate()), + ); + } + + @override + FutureOr validate() { + final WyattForm form = formRepository.accessForm(formName); + emit( + SignInState(form: form, status: form.validate()), + ); + } + + @override + FutureOr submit() async { + final WyattForm form = formRepository.accessForm(formName); + const error = '`submit()` is not implemented for BaseSignInCubit, ' + 'please use `signUpWithEmailAndPassword()`.'; + emit( + SignInState( + form: form, + errorMessage: error, + status: FormStatus.submissionFailure, + ), + ); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_anonymously.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_anonymously.dart new file mode 100644 index 00000000..fde28872 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_anonymously.dart @@ -0,0 +1,80 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/entities.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/sign_in_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Sign in mixin. +/// +/// Allows the user to sign in anonymously +/// +/// Gives access to the `signInAnonymously` method and +/// `onSignInAnonymously` callback. +mixin SignInAnonymously on BaseSignInCubit { + /// This callback is triggered when a user signs in anonymously. + FutureOrResult onSignInAnonymously( + Result result, + WyattForm form, + ); + + /// {@macro signin_anom} + FutureOr signInAnonymously() async { + if (state.status.isSubmissionInProgress) { + return; + } + + final form = formRepository.accessForm(formName); + emit(SignInState(form: form, status: FormStatus.submissionInProgress)); + + return CustomRoutine( + routine: authenticationRepository.signInAnonymously, + attachedLogic: (routineResult) => onSignInAnonymously( + routineResult, + form, + ), + onError: (error) { + emit( + SignInState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + SignedInEvent(account: account), + data: data, + ), + ); + emit( + SignInState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_email_password.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_email_password.dart new file mode 100644 index 00000000..616cde9b --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_email_password.dart @@ -0,0 +1,153 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/domain.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/sign_in_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Sign in mixin. +/// +/// Allows the user to sign in with email and password +/// +/// Gives access to the `signInWithEmailAndPassword` method and +/// `onSignInWithEmailAndPassword` callback. +mixin SignInWithEmailPassword on BaseSignInCubit { + /// This callback is triggered when a user signs in with email and password. + FutureOrResult onSignInWithEmailAndPassword( + Result result, + WyattForm form, + ); + + void emailChanged(String value) { + final emailValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.email) + .runtimeType; + assert( + emailValidatorType == Email, + 'Use emailCustomChanged(...) with validator $emailValidatorType', + ); + + final Email email = Email.dirty(value); + dataChanged(AuthFormField.email, email); + } + + void passwordChanged(String value) { + final passwordValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.password) + .runtimeType; + assert( + passwordValidatorType == Password, + 'Use passwordCustomChanged(...) with validator $passwordValidatorType', + ); + final Password password = Password.dirty(value); + dataChanged(AuthFormField.password, password); + } + + /// Same as [emailChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void emailCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.email, validator); + } + + /// Same as [passwordChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void passwordCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.password, validator); + } + + /// {@macro signin_pwd} + FutureOr signInWithEmailAndPassword() async { + if (state.status.isSubmissionInProgress) { + return; + } + + if (!state.status.isValidated) { + return; + } + + final form = formRepository.accessForm(formName); + emit( + SignInState( + form: form, + status: FormStatus.submissionInProgress, + ), + ); + + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { + emit( + SignInState( + form: form, + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + + return CustomRoutine( + routine: () => authenticationRepository.signInWithEmailAndPassword( + email: email!, + password: password!, + ), + attachedLogic: (routineResult) => onSignInWithEmailAndPassword( + routineResult, + form, + ), + onError: (error) { + emit( + SignInState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + SignedInEvent(account: account), + data: data, + ), + ); + emit( + SignInState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_google.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_google.dart new file mode 100644 index 00000000..1d814d19 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/mixin/sign_in_with_google.dart @@ -0,0 +1,79 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/utils/custom_routine.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/entities.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/sign_in_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Sign in mixin. +/// +/// Allows the user to sign in with google +/// +/// Gives access to the `signInWithGoogle` method and +/// `onSignInWithGoogle` callback. +mixin SignInWithGoogle on BaseSignInCubit { + /// This callback is triggered when a user signs in with google. + FutureOrResult onSignInWithGoogle( + Result result, + WyattForm form, + ); + + /// {@macro signin_google} + FutureOr signInWithGoogle() async { + if (state.status.isSubmissionInProgress) { + return; + } + final form = formRepository.accessForm(formName); + emit(SignInState(form: form, status: FormStatus.submissionInProgress)); + + return CustomRoutine( + routine: authenticationRepository.signInWithGoogle, + attachedLogic: (routineResult) => onSignInWithGoogle( + routineResult, + form, + ), + onError: (error) { + emit( + SignInState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + SignedInEvent(account: account), + data: data, + ), + ); + emit( + SignInState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart index 91262ce3..fbde339c 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,213 +16,51 @@ import 'dart:async'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/mixin/sign_in_anonymously.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/mixin/sign_in_with_email_password.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_in/cubit/mixin/sign_in_with_google.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +part 'base_sign_in_cubit.dart'; part 'sign_in_state.dart'; -class SignInCubit extends FormDataCubit { - SignInCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super( - SignInState( - form: authenticationRepository.formRepository - .accessForm(AuthFormName.signInForm), - ), - ); - final AuthenticationRepository _authenticationRepository; - FormRepository get _formRepository => - _authenticationRepository.formRepository; +/// {@template sign_in_cubit} +/// Fully featured sign in cubit. +/// +/// Sufficient in most cases. (Where fine granularity is not required.) +/// {@endtemplate} +class SignInCubit extends BaseSignInCubit + with + SignInAnonymously, + SignInWithEmailPassword, + SignInWithGoogle { + /// {@macro sign_in_cubit} + SignInCubit({required super.authenticationRepository}); @override - String get formName => AuthFormName.signInForm; - - void emailChanged(String value) { - final emailValidatorType = _formRepository - .accessForm(formName) - .validatorOf(AuthFormField.email) - .runtimeType; - assert( - emailValidatorType == Email, - 'Use emailCustomChanged(...) with validator $emailValidatorType', - ); - - final Email email = Email.dirty(value); - dataChanged(AuthFormField.email, email); - } - - void passwordChanged(String value) { - final passwordValidatorType = _formRepository - .accessForm(formName) - .validatorOf(AuthFormField.password) - .runtimeType; - assert( - passwordValidatorType == Password, - 'Use passwordCustomChanged(...) with validator $passwordValidatorType', - ); - final Password password = Password.dirty(value); - dataChanged(AuthFormField.password, password); - } - - /// Same as [emailChanged] but with a custom [Validator]. - /// - /// Sort of short hand for [dataChanged]. - void emailCustomChanged< - Validator extends FormInputValidator>( - Validator validator, - ) { - dataChanged(AuthFormField.email, validator); - } - - /// Same as [passwordChanged] but with a custom [Validator]. - /// - /// Sort of short hand for [dataChanged]. - void passwordCustomChanged< - Validator extends FormInputValidator>( - Validator validator, - ) { - dataChanged(AuthFormField.password, validator); - } + FutureOrResult onSignInAnonymously( + Result result, + WyattForm form, + ) => + const Ok(null); @override - FutureOr dataChanged( - String key, - FormInputValidator dirtyValue, - ) { - final form = _formRepository.accessForm(formName).clone(); - - try { - form.updateValidator(key, dirtyValue); - _formRepository.updateForm(form); - } catch (e) { - rethrow; - } - - emit( - state.copyWith(form: form, status: form.validate()), - ); - } + FutureOrResult onSignInWithEmailAndPassword( + Result result, + WyattForm form, + ) => + const Ok(null); @override - FutureOr reset() { - final form = state.form.reset(); - _formRepository.updateForm(form); - emit( - state.copyWith(form: form, status: form.validate()), - ); - } - - @override - FutureOr submit() async { - throw UnimplementedError('`submit()` is not implemented for SignInCubit, ' - 'please use `signInWithEmailAndPassword()` or `signInAnonymously()`'); - } - - @override - FutureOr update( - WyattForm form, { - SetOperation operation = SetOperation.replace, - }) { - final WyattForm current = _formRepository.accessForm(formName).clone(); - final WyattForm newForm = operation.operation.call(current, form); - _formRepository.updateForm(newForm); - - emit( - state.copyWith( - form: newForm, - status: newForm.validate(), - ), - ); - } - - @override - FutureOr validate() { - emit( - state.copyWith( - status: _formRepository.accessForm(formName).validate(), - ), - ); - } - - FutureOr signInWithEmailAndPassword() async { - if (state.status.isSubmissionInProgress) { - return; - } - - if (!state.status.isValidated) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - - final form = _formRepository.accessForm(formName); - final email = form.valueOf(AuthFormField.email); - final password = form.valueOf(AuthFormField.password); - - if (email.isNullOrEmpty || password.isNullOrEmpty) { - emit( - state.copyWith( - errorMessage: 'An error occured while retrieving data from the form.', - status: FormStatus.submissionFailure, - ), - ); - } - - final uid = await _authenticationRepository.signInWithEmailAndPassword( - email: email!, - password: password!, - ); - - emit( - uid.fold( - (value) => state.copyWith(status: FormStatus.submissionSuccess), - (error) => state.copyWith( - errorMessage: error.message, - status: FormStatus.submissionFailure, - ), - ), - ); - } - - FutureOr signInAnonymously() async { - if (state.status.isSubmissionInProgress) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - - final uid = await _authenticationRepository.signInAnonymously(); - - emit( - uid.fold( - (value) => state.copyWith(status: FormStatus.submissionSuccess), - (error) => state.copyWith( - errorMessage: error.message, - status: FormStatus.submissionFailure, - ), - ), - ); - } - - FutureOr signInWithGoogle() async { - if (state.status.isSubmissionInProgress) { - return; - } - // TODO(wyatt): maybe emit new state (to not carry an old errorMessage) - emit(state.copyWith(status: FormStatus.submissionInProgress)); - - final uid = await _authenticationRepository.signInWithGoogle(); - - emit( - uid.fold( - (value) => state.copyWith(status: FormStatus.submissionSuccess), - (error) => state.copyWith( - errorMessage: error.message, - status: FormStatus.submissionFailure, - ), - ), - ); - } + FutureOrResult onSignInWithGoogle( + Result result, + WyattForm form, + ) => + const Ok(null); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart index d98472ad..39ed623f 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,14 +16,22 @@ part of 'sign_in_cubit.dart'; +/// {@template sign_in_state} +/// Sign in cubit state to manage the form. +/// {@endtemplate} class SignInState extends FormDataState { + /// {@macro sign_in_state} const SignInState({ required super.form, super.status = FormStatus.pure, super.errorMessage, }); + + /// Email validator of the form FormInputValidator get email => form.validatorOf(AuthFormField.email); + + /// Password validator of the form FormInputValidator get password => form.validatorOf(AuthFormField.password); diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/listener/sign_in_listener.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/listener/sign_in_listener.dart index e51a1edd..2d55fe16 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/listener/sign_in_listener.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/listener/sign_in_listener.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -19,7 +19,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/src/features/sign_in/sign_in.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class SignInListener extends StatelessWidget { +/// {@template sign_in_listener} +/// Widget that listens and builds a child based on the state of +/// the sign in cubit +/// {@endtemplate} +class SignInListener extends StatelessWidget { + /// {@macro sign_in_listener} const SignInListener({ required this.child, this.onProgress, @@ -29,19 +34,29 @@ class SignInListener extends StatelessWidget { super.key, }); + /// Callback to show when the sign in is in progress final void Function(BuildContext context)? onProgress; + + /// Callback to show when the sign in is successful final void Function(BuildContext context)? onSuccess; + + /// Callback to show when the sign in is unsuccessful final void Function( BuildContext context, FormStatus status, String? errorMessage, )? onError; + + /// Custom builder to show when the sign in is in progress, successful, or + /// unsuccessful final void Function(BuildContext context, SignInState state)? customBuilder; + + /// Child of the widget final Widget child; @override Widget build(BuildContext context) => - BlocListener, SignInState>( + BlocListener, SignInState>( listener: (context, state) { if (customBuilder != null) { return customBuilder!(context, state); diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart index 88fb9a39..37336de7 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,5 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +export 'cubit/mixin/sign_in_anonymously.dart'; +export 'cubit/mixin/sign_in_with_email_password.dart'; +export 'cubit/mixin/sign_in_with_google.dart'; export 'cubit/sign_in_cubit.dart'; export 'listener/sign_in_listener.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/base_sign_up_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/base_sign_up_cubit.dart new file mode 100644 index 00000000..3691f4c5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/base_sign_up_cubit.dart @@ -0,0 +1,108 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'sign_up_cubit.dart'; + +/// {@template base_sign_up_cubit} +/// Abstract sign up cubit useful for implementing a cubit with fine +/// granularity by adding only the required mixins. +/// {@endtemplate} +abstract class BaseSignUpCubit extends FormDataCubit { + /// {@macro base_sign_up_cubit} + BaseSignUpCubit({ + required this.authenticationRepository, + }) : super( + SignUpState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signUpForm), + ), + ); + + /// The authentication repository. + final AuthenticationRepository authenticationRepository; + FormRepository get formRepository => authenticationRepository.formRepository; + + @override + String get formName => AuthFormName.signUpForm; + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = formRepository.accessForm(formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + formRepository.updateForm(form); + } catch (e) { + rethrow; + } + + emit( + SignUpState(form: form, status: form.validate()), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + formRepository.updateForm(form); + emit( + SignUpState(form: form, status: form.validate()), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + formRepository.updateForm(newForm); + + emit( + SignUpState( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr validate() { + final WyattForm form = formRepository.accessForm(formName); + emit( + SignUpState(form: form, status: form.validate()), + ); + } + + @override + FutureOr submit() async { + final WyattForm form = formRepository.accessForm(formName); + const error = '`submit()` is not implemented for BaseSignUpCubit, ' + 'please use `signUpWithEmailAndPassword()`.'; + emit( + SignUpState( + form: form, + errorMessage: error, + status: FormStatus.submissionFailure, + ), + ); + throw UnimplementedError(error); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/mixin/sign_up_with_email_password.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/mixin/sign_up_with_email_password.dart new file mode 100644 index 00000000..80d56b7b --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/mixin/sign_up_with_email_password.dart @@ -0,0 +1,143 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +/// Sign up mixin. +/// +/// Allows the user to register with an email and a password. +/// +/// Gives access to the `signUpWithEmailPassword` method and +/// `onSignUpWithEmailAndPassword` callback. +mixin SignUpWithEmailPassword on BaseSignUpCubit { + /// This callback is triggered when a user creates an account. + /// + /// For example: when a user sign up in firebase. + FutureOrResult onSignUpWithEmailAndPassword( + Result result, + WyattForm form, + ); + + void emailChanged(String value) { + final emailValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.email) + .runtimeType; + assert( + emailValidatorType == Email, + 'Use emailCustomChanged(...) with validator $emailValidatorType', + ); + + final Email email = Email.dirty(value); + dataChanged(AuthFormField.email, email); + } + + void passwordChanged(String value) { + final passwordValidatorType = formRepository + .accessForm(formName) + .validatorOf(AuthFormField.password) + .runtimeType; + assert( + passwordValidatorType == Password, + 'Use passwordCustomChanged(...) with validator $passwordValidatorType', + ); + final Password password = Password.dirty(value); + dataChanged(AuthFormField.password, password); + } + + /// Same as [emailChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void emailCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.email, validator); + } + + /// Same as [passwordChanged] but with a custom [Validator]. + /// + /// Sort of short hand for [dataChanged]. + void passwordCustomChanged< + Validator extends FormInputValidator>( + Validator validator, + ) { + dataChanged(AuthFormField.password, validator); + } + + /// {@macro signup_pwd} + FutureOr signUpWithEmailPassword() async { + if (!state.status.isValidated) { + return; + } + + final form = formRepository.accessForm(formName); + emit(SignUpState(form: form, status: FormStatus.submissionInProgress)); + + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { + emit( + SignUpState( + form: form, + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + + return CustomRoutine( + routine: () => authenticationRepository.signUpWithEmailAndPassword( + email: email!, + password: password!, + ), + attachedLogic: (routineResult) => onSignUpWithEmailAndPassword( + routineResult, + form, + ), + onError: (error) { + emit( + SignUpState( + form: form, + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ); + addError(error); + }, + onSuccess: (account, data) { + authenticationRepository.addSession( + AuthenticationSession.fromEvent( + SignedUpEvent(account: account), + data: data, + ), + ); + emit( + SignUpState( + form: form, + status: FormStatus.submissionSuccess, + ), + ); + }, + ).call(); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart index 2d7ed28b..09a76667 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,166 +16,32 @@ import 'dart:async'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_authentication_bloc/src/features/sign_up/cubit/mixin/sign_up_with_email_password.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +part 'base_sign_up_cubit.dart'; part 'sign_up_state.dart'; -class SignUpCubit extends FormDataCubit { - SignUpCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super( - SignUpState( - form: authenticationRepository.formRepository - .accessForm(AuthFormName.signUpForm), - ), - ); - final AuthenticationRepository _authenticationRepository; - FormRepository get _formRepository => - _authenticationRepository.formRepository; +/// {@template sign_up_cubit} +/// Fully featured sign up cubit. +/// +/// Sufficient in most cases. (Where fine granularity is not required.) +/// {@endtemplate} +class SignUpCubit extends BaseSignUpCubit + with SignUpWithEmailPassword { + /// {@macro sign_up_cubit} + SignUpCubit({required super.authenticationRepository}); @override - String get formName => AuthFormName.signUpForm; - - void emailChanged(String value) { - final emailValidatorType = _formRepository - .accessForm(formName) - .validatorOf(AuthFormField.email) - .runtimeType; - assert( - emailValidatorType == Email, - 'Use emailCustomChanged(...) with validator $emailValidatorType', - ); - - final Email email = Email.dirty(value); - dataChanged(AuthFormField.email, email); - } - - void passwordChanged(String value) { - final passwordValidatorType = _formRepository - .accessForm(formName) - .validatorOf(AuthFormField.password) - .runtimeType; - assert( - passwordValidatorType == Password, - 'Use passwordCustomChanged(...) with validator $passwordValidatorType', - ); - final Password password = Password.dirty(value); - dataChanged(AuthFormField.password, password); - } - - /// Same as [emailChanged] but with a custom [Validator]. - /// - /// Sort of short hand for [dataChanged]. - void emailCustomChanged< - Validator extends FormInputValidator>( - Validator validator, - ) { - dataChanged(AuthFormField.email, validator); - } - - /// Same as [passwordChanged] but with a custom [Validator]. - /// - /// Sort of short hand for [dataChanged]. - void passwordCustomChanged< - Validator extends FormInputValidator>( - Validator validator, - ) { - dataChanged(AuthFormField.password, validator); - } - - @override - FutureOr dataChanged( - String key, - FormInputValidator dirtyValue, - ) { - final form = _formRepository.accessForm(formName).clone(); - - try { - form.updateValidator(key, dirtyValue); - _formRepository.updateForm(form); - } catch (e) { - rethrow; - } - - emit( - state.copyWith(form: form, status: form.validate()), - ); - } - - @override - FutureOr reset() { - final form = state.form.reset(); - _formRepository.updateForm(form); - emit( - state.copyWith(form: form, status: form.validate()), - ); - } - - @override - FutureOr submit() async { - if (!state.status.isValidated) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - - final form = _formRepository.accessForm(formName); - final email = form.valueOf(AuthFormField.email); - final password = form.valueOf(AuthFormField.password); - - if (email.isNullOrEmpty || password.isNullOrEmpty) { - emit( - state.copyWith( - errorMessage: 'An error occured while retrieving data from the form.', - status: FormStatus.submissionFailure, - ), - ); - } - - final uid = await _authenticationRepository.signUp( - email: email!, - password: password!, - ); - - emit( - uid.fold( - (value) => state.copyWith(status: FormStatus.submissionSuccess), - (error) => state.copyWith( - errorMessage: error.message, - status: FormStatus.submissionFailure, - ), - ), - ); - } - - @override - FutureOr update( - WyattForm form, { - SetOperation operation = SetOperation.replace, - }) { - final WyattForm current = _formRepository.accessForm(formName).clone(); - final WyattForm newForm = operation.operation.call(current, form); - _formRepository.updateForm(newForm); - - emit( - state.copyWith( - form: newForm, - status: newForm.validate(), - ), - ); - } - - @override - FutureOr validate() { - emit( - state.copyWith( - status: _formRepository.accessForm(formName).validate(), - ), - ); - } + FutureOrResult onSignUpWithEmailAndPassword( + Result result, + WyattForm form, + ) => + const Ok(null); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart index 40c870c5..ac04efd5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -16,14 +16,22 @@ part of 'sign_up_cubit.dart'; +/// {@template sign_up_state} +/// Sign up cubit state to manage the form. +/// {@endtemplate} class SignUpState extends FormDataState { + /// {@macro sign_up_state} const SignUpState({ required super.form, super.status = FormStatus.pure, super.errorMessage, }); + + /// Email validator of the form FormInputValidator get email => form.validatorOf(AuthFormField.email); + + /// Password validator of the form FormInputValidator get password => form.validatorOf(AuthFormField.password); @@ -41,7 +49,6 @@ class SignUpState extends FormDataState { @override List get props => [email, password, status, form]; - @override @override String toString() => 'SignUpState(status: ${status.name} ' '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/listener/sign_up_listener.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/listener/sign_up_listener.dart index 925f0294..b4e5ad39 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/listener/sign_up_listener.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/listener/sign_up_listener.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -19,7 +19,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/src/features/sign_up/cubit/sign_up_cubit.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class SignUpListener extends StatelessWidget { +/// {@template sign_up_listener} +/// Widget that listens and builds a child based on the state of +/// the sign up cubit +/// {@endtemplate} +class SignUpListener extends StatelessWidget { + /// {@macro sign_up_listener} const SignUpListener({ required this.child, this.onProgress, @@ -29,19 +34,29 @@ class SignUpListener extends StatelessWidget { super.key, }); + /// Callback to show when the sign up is in progress final void Function(BuildContext context)? onProgress; + + /// Callback to show when the sign up is successful final void Function(BuildContext context)? onSuccess; + + /// Callback to show when the sign up is unsuccessful final void Function( BuildContext context, FormStatus status, String? errorMessage, )? onError; + + /// Custom builder to show when the sign up is in progress, successful, or + /// unsuccessful final void Function(BuildContext context, SignUpState state)? customBuilder; + + /// Child of the widget final Widget child; @override Widget build(BuildContext context) => - BlocListener, SignUpState>( + BlocListener, SignUpState>( listener: (context, state) { if (customBuilder != null) { return customBuilder!(context, state); diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart index 0eb01f0e..21c5895e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,5 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +export 'cubit/mixin/sign_up_with_email_password.dart'; export 'cubit/sign_up_cubit.dart'; export 'listener/sign_up_listener.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/src.dart b/packages/wyatt_authentication_bloc/lib/src/src.dart index 3a660ea4..18df157b 100644 --- a/packages/wyatt_authentication_bloc/lib/src/src.dart +++ b/packages/wyatt_authentication_bloc/lib/src/src.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/lib/wyatt_authentication_bloc.dart b/packages/wyatt_authentication_bloc/lib/wyatt_authentication_bloc.dart index a010cfa4..4ed48bd0 100644 --- a/packages/wyatt_authentication_bloc/lib/wyatt_authentication_bloc.dart +++ b/packages/wyatt_authentication_bloc/lib/wyatt_authentication_bloc.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -17,7 +17,4 @@ /// An authentication library for BLoC. library wyatt_authentication_bloc; -export 'package:firebase_auth/firebase_auth.dart'; -export 'package:google_sign_in/google_sign_in.dart'; - export 'src/src.dart'; diff --git a/packages/wyatt_authentication_bloc/pubspec.yaml b/packages/wyatt_authentication_bloc/pubspec.yaml index a97dba05..6c8e1f57 100644 --- a/packages/wyatt_authentication_bloc/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/pubspec.yaml @@ -29,6 +29,8 @@ dependencies: wyatt_type_utils: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ version: ^0.0.4 + flutter_secure_storage: ^8.0.0 + http: ^0.13.5 dev_dependencies: flutter_test: { sdk: flutter } @@ -37,4 +39,4 @@ dev_dependencies: wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ - version: 2.4.1 + version: ^2.4.1 diff --git a/packages/wyatt_authentication_bloc/test/authentication/authentication_cubit_test.dart b/packages/wyatt_authentication_bloc/test/authentication/authentication_cubit_test.dart index e836bd4f..5469c51b 100644 --- a/packages/wyatt_authentication_bloc/test/authentication/authentication_cubit_test.dart +++ b/packages/wyatt_authentication_bloc/test/authentication/authentication_cubit_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -26,25 +26,55 @@ class MockAuthenticationRepository extends Mock class MockAccount extends Mock implements Account {} +class TestAuthenticationCubit extends AuthenticationCubit { + TestAuthenticationCubit({required super.authenticationRepository}); + + @override + FutureOrResult onDelete() async => const Ok(null); + + @override + FutureOrResult onReauthenticate( + Result result, + ) async => + const Ok(null); + + @override + FutureOrResult onRefresh(Result result) async => + const Ok(null); + + @override + FutureOrResult onSignInFromCache( + AuthenticationSession session, + ) async => + const Ok(null); + + @override + FutureOrResult onSignOut() async => const Ok(null); +} + void main() { group('AuthenticationCubit', () { final MockAccount account = MockAccount(); - final AccountWrapper wrapper = AccountWrapperModel(account, 10); + final AuthenticationSession session = AuthenticationSession( + latestEvent: const UnknownAuthenticationEvent(), + account: account, + data: 10, + ); late AuthenticationRepository authenticationRepository; setUp(() { authenticationRepository = MockAuthenticationRepository(); - when(() => authenticationRepository.streamAccount()).thenAnswer( + when(() => authenticationRepository.sessionStream()).thenAnswer( (_) => const Stream.empty(), ); - when( - () => authenticationRepository.getAccount(), - ).thenAnswer((_) async => Ok(account)); + when(() => authenticationRepository.checkForCachedAccount()).thenAnswer( + (_) => Future.value(), + ); }); test('initial auth state is `unknown`', () { expect( - AuthenticationCubit( + TestAuthenticationCubit( authenticationRepository: authenticationRepository, ).state, const AuthenticationState.unknown(), @@ -53,59 +83,29 @@ void main() { group('ListenForAuthenticationChanges', () { blocTest, AuthenticationState>( - 'emits authenticated when stream contains account', + 'emits authenticated when stream contains session', setUp: () { - when(() => authenticationRepository.streamAccount()).thenAnswer( - (_) => Stream.fromIterable([ - Future.value( - Ok(wrapper), - ) - ]), + when(() => authenticationRepository.sessionStream()).thenAnswer( + (_) => Stream.fromIterable([session]), ); }, - build: () => AuthenticationCubit( + build: () => TestAuthenticationCubit( authenticationRepository: authenticationRepository, ), seed: () => const AuthenticationState.unknown(), - expect: () => [AuthenticationState.authenticated(wrapper)], + expect: () => [AuthenticationState.authenticated(session)], ); blocTest, AuthenticationState>( 'emits unauthenticated when account stream is empty', setUp: () { - when( - () => authenticationRepository.destroyCache(), - ).thenAnswer((_) async => const Ok(null)); - when(() => authenticationRepository.streamAccount()).thenAnswer( - (_) => Stream.fromIterable([ - Future.value( - Ok(AccountWrapperModel(null, 1)), - ) - ]), + when(() => authenticationRepository.sessionStream()).thenAnswer( + (_) => Stream.fromIterable( + [const AuthenticationSession(latestEvent: SignedOutEvent())], + ), ); }, - build: () => AuthenticationCubit( - authenticationRepository: authenticationRepository, - ), - seed: () => const AuthenticationState.unknown(), - expect: () => [const AuthenticationState.unauthenticated()], - ); - - blocTest, AuthenticationState>( - 'emits unauthenticated when there is an error in stream', - setUp: () { - when( - () => authenticationRepository.destroyCache(), - ).thenAnswer((_) async => const Ok(null)); - when(() => authenticationRepository.streamAccount()).thenAnswer( - (_) => Stream.fromIterable([ - Future.value( - Err(ServerException()), - ) - ]), - ); - }, - build: () => AuthenticationCubit( + build: () => TestAuthenticationCubit( authenticationRepository: authenticationRepository, ), seed: () => const AuthenticationState.unknown(), @@ -121,7 +121,7 @@ void main() { () => authenticationRepository.signOut(), ).thenAnswer((_) async => const Ok(null)); }, - build: () => AuthenticationCubit( + build: () => TestAuthenticationCubit( authenticationRepository: authenticationRepository, ), act: (cubit) => cubit.signOut(), diff --git a/packages/wyatt_authentication_bloc/test/authentication/authentication_state_test.dart b/packages/wyatt_authentication_bloc/test/authentication/authentication_state_test.dart index a85c7998..9566f2f3 100644 --- a/packages/wyatt_authentication_bloc/test/authentication/authentication_state_test.dart +++ b/packages/wyatt_authentication_bloc/test/authentication/authentication_state_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -27,7 +27,7 @@ void main() { const AuthenticationState state = AuthenticationState.unauthenticated(); expect(state.status, AuthenticationStatus.unauthenticated); - expect(state.accountWrapper, null); + expect(state.session, null); }); }); @@ -36,10 +36,12 @@ void main() { final MockAccount account = MockAccount(); final AuthenticationState state = AuthenticationState.authenticated( - AccountWrapperModel(account, null), + AuthenticationSession.fromEvent( + SignedInEvent(account: account), + ), ); expect(state.status, AuthenticationStatus.authenticated); - expect(state.accountWrapper?.account, account); + expect(state.session?.account, account); }); }); @@ -49,11 +51,14 @@ void main() { const String extra = 'AwesomeExtraData'; final AuthenticationState state = AuthenticationState.authenticated( - AccountWrapperModel(account, extra), + AuthenticationSession.fromEvent( + SignedInEvent(account: account), + data: extra, + ), ); expect(state.status, AuthenticationStatus.authenticated); - expect(state.accountWrapper?.account, account); - expect(state.accountWrapper?.data, extra); + expect(state.session?.account, account); + expect(state.session?.data, extra); }); }); }); diff --git a/packages/wyatt_authentication_bloc/test/email_verification/email_verification_cubit_test.dart b/packages/wyatt_authentication_bloc/test/email_verification/email_verification_cubit_test.dart index 05ea7a74..29e0c9b4 100644 --- a/packages/wyatt_authentication_bloc/test/email_verification/email_verification_cubit_test.dart +++ b/packages/wyatt_authentication_bloc/test/email_verification/email_verification_cubit_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -39,15 +39,32 @@ void main() { setUp(() { authenticationRepository = MockAuthenticationRepository(); + account = MockAccount(); + + when(() => authenticationRepository.sessionStream()).thenAnswer( + (_) => Stream.fromIterable([ + AuthenticationSession.fromEvent( + SignedInFromCacheEvent(account: account), + data: 10, + ) + ]), + ); + when( - () => authenticationRepository.getAccount(), - ).thenAnswer((_) async => Ok(account)); + () => authenticationRepository.currentSession(), + ).thenAnswer( + (_) async => Ok( + AuthenticationSession.fromEvent( + SignedInFromCacheEvent(account: account), + data: 10, + ), + ), + ); when( () => authenticationRepository.refresh(), - ).thenAnswer((_) async => const Ok(null)); + ).thenAnswer((_) async => Ok(account)); - account = MockAccount(); when( () => account.emailVerified, ).thenAnswer((_) => true); @@ -104,7 +121,7 @@ void main() { 'emits failure', setUp: () { when(() => authenticationRepository.sendEmailVerification()) - .thenAnswer((_) async => Err(ServerException('erreur'))); + .thenAnswer((_) async => const Err(ServerException('erreur'))); }, build: () => EmailVerificationCubit( authenticationRepository: authenticationRepository, @@ -129,7 +146,7 @@ void main() { setUp: () { when( () => authenticationRepository.refresh(), - ).thenAnswer((_) async => const Ok(null)); + ).thenAnswer((_) async => Ok(account)); }, build: () => EmailVerificationCubit( authenticationRepository: authenticationRepository, @@ -145,7 +162,7 @@ void main() { setUp: () { when( () => authenticationRepository.refresh(), - ).thenAnswer((_) async => const Ok(null)); + ).thenAnswer((_) async => Ok(account)); when(() => account.emailVerified).thenAnswer((_) => false); }, build: () => EmailVerificationCubit( @@ -161,7 +178,7 @@ void main() { 'emits success with true if verified', setUp: () { when(() => authenticationRepository.refresh()) - .thenAnswer((_) async => const Ok(null)); + .thenAnswer((_) async => Ok(account)); }, build: () => EmailVerificationCubit( authenticationRepository: authenticationRepository, @@ -183,7 +200,7 @@ void main() { 'emits success with false if not verified', setUp: () { when(() => authenticationRepository.refresh()) - .thenAnswer((_) async => const Ok(null)); + .thenAnswer((_) async => Ok(account)); when(() => account.emailVerified).thenAnswer((_) => false); }, build: () => EmailVerificationCubit( @@ -205,29 +222,7 @@ void main() { 'emits failure on refresh error', setUp: () { when(() => authenticationRepository.refresh()) - .thenAnswer((_) async => Err(ServerException('erreur'))); - }, - build: () => EmailVerificationCubit( - authenticationRepository: authenticationRepository, - ), - seed: () => const EmailVerificationState(), - act: (cubit) => cubit.checkEmailVerification(), - expect: () => [ - const EmailVerificationState( - status: FormStatus.submissionInProgress, - ), - const EmailVerificationState( - errorMessage: 'erreur', - status: FormStatus.submissionFailure, - ) - ], - ); - - blocTest, EmailVerificationState>( - 'emits failure on get account error', - setUp: () { - when(() => authenticationRepository.getAccount()) - .thenAnswer((_) async => Err(ServerException('erreur'))); + .thenAnswer((_) async => const Err(ServerException('erreur'))); }, build: () => EmailVerificationCubit( authenticationRepository: authenticationRepository, diff --git a/packages/wyatt_authentication_bloc/test/email_verification/email_verification_state_test.dart b/packages/wyatt_authentication_bloc/test/email_verification/email_verification_state_test.dart index 37e030b4..cf779daa 100644 --- a/packages/wyatt_authentication_bloc/test/email_verification/email_verification_state_test.dart +++ b/packages/wyatt_authentication_bloc/test/email_verification/email_verification_state_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/test/password_reset/password_reset_cubit_test.dart b/packages/wyatt_authentication_bloc/test/password_reset/password_reset_cubit_test.dart index ab37fcd3..11c98b59 100644 --- a/packages/wyatt_authentication_bloc/test/password_reset/password_reset_cubit_test.dart +++ b/packages/wyatt_authentication_bloc/test/password_reset/password_reset_cubit_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -272,7 +272,7 @@ void main() { () => authenticationRepository.sendPasswordResetEmail( email: any(named: 'email'), ), - ).thenAnswer((_) async => Err(ServerException())); + ).thenAnswer((_) async => const Err(ServerException())); when( () => formRepository.accessForm(AuthFormName.passwordResetForm), ).thenAnswer( diff --git a/packages/wyatt_authentication_bloc/test/password_reset/password_reset_state_test.dart b/packages/wyatt_authentication_bloc/test/password_reset/password_reset_state_test.dart index 661ea241..518be2dc 100644 --- a/packages/wyatt_authentication_bloc/test/password_reset/password_reset_state_test.dart +++ b/packages/wyatt_authentication_bloc/test/password_reset/password_reset_state_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/test/sign_in/sign_in_cubit_test.dart b/packages/wyatt_authentication_bloc/test/sign_in/sign_in_cubit_test.dart index 622bfb79..bc517187 100644 --- a/packages/wyatt_authentication_bloc/test/sign_in/sign_in_cubit_test.dart +++ b/packages/wyatt_authentication_bloc/test/sign_in/sign_in_cubit_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -435,7 +435,7 @@ void main() { email: any(named: 'email'), password: any(named: 'password'), ), - ).thenAnswer((_) async => Err(ServerException())); + ).thenAnswer((_) async => const Err(ServerException())); when( () => formRepository.accessForm(AuthFormName.signInForm), ).thenAnswer( @@ -579,11 +579,11 @@ void main() { [ FormInput( AuthFormField.email, - const Email.dirty(validEmailString), + const Email.pure(), ), FormInput( AuthFormField.password, - const Password.dirty(validPasswordString), + const Password.pure(), ) ], name: AuthFormName.signInForm, @@ -595,11 +595,11 @@ void main() { [ FormInput( AuthFormField.email, - const Email.dirty(validEmailString), + const Email.pure(), ), FormInput( AuthFormField.password, - const Password.dirty(validPasswordString), + const Password.pure(), ) ], name: AuthFormName.signInForm, @@ -615,7 +615,7 @@ void main() { setUp: () { when( () => authenticationRepository.signInAnonymously(), - ).thenAnswer((_) async => Err(ServerException())); + ).thenAnswer((_) async => const Err(ServerException())); }, build: () => SignInCubit( authenticationRepository: authenticationRepository, @@ -643,11 +643,11 @@ void main() { [ FormInput( AuthFormField.email, - const Email.dirty(validEmailString), + const Email.pure(), ), FormInput( AuthFormField.password, - const Password.dirty(validPasswordString), + const Password.pure(), ) ], name: AuthFormName.signInForm, @@ -659,11 +659,11 @@ void main() { [ FormInput( AuthFormField.email, - const Email.dirty(validEmailString), + const Email.pure(), ), FormInput( AuthFormField.password, - const Password.dirty(validPasswordString), + const Password.pure(), ) ], name: AuthFormName.signInForm, diff --git a/packages/wyatt_authentication_bloc/test/sign_in/sign_in_state_test.dart b/packages/wyatt_authentication_bloc/test/sign_in/sign_in_state_test.dart index e55d92bd..30f40cb7 100644 --- a/packages/wyatt_authentication_bloc/test/sign_in/sign_in_state_test.dart +++ b/packages/wyatt_authentication_bloc/test/sign_in/sign_in_state_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_authentication_bloc/test/sign_up/sign_up_cubit_test.dart b/packages/wyatt_authentication_bloc/test/sign_up/sign_up_cubit_test.dart index cc966202..d437c339 100644 --- a/packages/wyatt_authentication_bloc/test/sign_up/sign_up_cubit_test.dart +++ b/packages/wyatt_authentication_bloc/test/sign_up/sign_up_cubit_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -59,7 +59,7 @@ void main() { formRepository = MockFormRepository(); when( - () => authenticationRepository.signUp( + () => authenticationRepository.signUpWithEmailAndPassword( email: any(named: 'email'), password: any(named: 'password'), ), @@ -258,13 +258,13 @@ void main() { ); }); - group('submit', () { + group('signUpWithEmailPassword', () { blocTest, SignUpState>( 'does nothing when status is not validated', build: () => SignUpCubit( authenticationRepository: authenticationRepository, ), - act: (cubit) => cubit.submit(), + act: (cubit) => cubit.signUpWithEmailPassword(), expect: () => const [], ); @@ -308,10 +308,10 @@ void main() { ), status: FormStatus.valid, ), - act: (cubit) => cubit.submit(), + act: (cubit) => cubit.signUpWithEmailPassword(), verify: (_) { verify( - () => authenticationRepository.signUp( + () => authenticationRepository.signUpWithEmailAndPassword( email: validEmailString, password: validPasswordString, ), @@ -360,7 +360,7 @@ void main() { ), status: FormStatus.valid, ), - act: (cubit) => cubit.submit(), + act: (cubit) => cubit.signUpWithEmailPassword(), expect: () => [ SignUpState( form: WyattFormImpl( @@ -402,11 +402,11 @@ void main() { 'when signUp fails', setUp: () { when( - () => authenticationRepository.signUp( + () => authenticationRepository.signUpWithEmailAndPassword( email: any(named: 'email'), password: any(named: 'password'), ), - ).thenAnswer((_) async => Err(ServerException())); + ).thenAnswer((_) async => const Err(ServerException())); when( () => formRepository.accessForm(AuthFormName.signUpForm), ).thenAnswer( @@ -444,7 +444,7 @@ void main() { ), status: FormStatus.valid, ), - act: (cubit) => cubit.submit(), + act: (cubit) => cubit.signUpWithEmailPassword(), expect: () => [ SignUpState( form: WyattFormImpl( diff --git a/packages/wyatt_authentication_bloc/test/sign_up/sign_up_state_test.dart b/packages/wyatt_authentication_bloc/test/sign_up/sign_up_state_test.dart index 6e67399a..89380d66 100644 --- a/packages/wyatt_authentication_bloc/test/sign_up/sign_up_state_test.dart +++ b/packages/wyatt_authentication_bloc/test/sign_up/sign_up_state_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_bloc_helper/.gitignore b/packages/wyatt_bloc_helper/.gitignore deleted file mode 100644 index 65c34dc8..00000000 --- a/packages/wyatt_bloc_helper/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_bloc_helper/.gitignore b/packages/wyatt_bloc_helper/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_bloc_helper/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/.pubignore b/packages/wyatt_bloc_helper/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_bloc_helper/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/AUTHORS b/packages/wyatt_bloc_helper/AUTHORS deleted file mode 100644 index 2a0b50f7..00000000 --- a/packages/wyatt_bloc_helper/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Malo Léon -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/AUTHORS b/packages/wyatt_bloc_helper/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_bloc_helper/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/LICENSE b/packages/wyatt_bloc_helper/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_bloc_helper/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/LICENSE b/packages/wyatt_bloc_helper/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_bloc_helper/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/README.md b/packages/wyatt_bloc_helper/README.md index 5b055eb4..ea4ffd4f 100644 --- a/packages/wyatt_bloc_helper/README.md +++ b/packages/wyatt_bloc_helper/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. * - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,12 +16,10 @@ * along with this program. If not, see . --> -# Flutter - BloC Helper +# BloC Helper

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Flutter

@@ -86,7 +84,7 @@ Widget buildChild(BuildContext context) { } ``` -> Note: here, you can use BlocBuilder, BlocListener,... and access Bloc and Repository instance with the mixin helper. +> Note: here, you can use BlocBuilder, BlocListener, ... and access Bloc and Repository instance with the mixin helper. ### Only BlocConsumer @@ -116,7 +114,7 @@ Widget onBuild(BuildContext context, CounterState state) { } ``` -If needed, you can wrap what depends on the state with the function `parent`. +If needed, you can wrap what depends on the state with the function `parent` . ```dart @override @@ -129,7 +127,7 @@ Widget parent(BuildContext context, Widget child) { ); ``` -> Note: you can override `onBuild`, but also `onListen`, `shouldBuildWhen` and `shouldListenWhen` methods. +> Note: you can override `onBuild` , but also `onListen` , `shouldBuildWhen` and `shouldListenWhen` methods. ### Both BlocProvider and BlocConsumer diff --git a/packages/wyatt_bloc_helper/analysis_options.yaml b/packages/wyatt_bloc_helper/analysis_options.yaml index b0c6aced..8c9daa4e 100644 --- a/packages/wyatt_bloc_helper/analysis_options.yaml +++ b/packages/wyatt_bloc_helper/analysis_options.yaml @@ -1,4 +1 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml - -analyzer: - exclude: "!example/**" \ No newline at end of file diff --git a/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart b/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart index 046da441..9ac68ddb 100644 --- a/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart +++ b/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart @@ -17,7 +17,12 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +/// A utility class that provides a way to create a [BlocProvider] or +/// [RepositoryProvider] with a [Bloc] or Repository that is already +/// available in the widget tree. abstract class SmartProvider { + /// Creates a [BlocProvider] with a [Bloc] that is possibly already + /// available in the widget tree. static BlocProvider bloc, State extends Object>( BuildContext context, { @@ -45,6 +50,8 @@ abstract class SmartProvider { ); } + /// Creates a [RepositoryProvider] with a Repository that is possibly + /// already available in the widget tree. static RepositoryProvider repo( BuildContext context, { required Repository Function(BuildContext) create, diff --git a/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart b/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart index 4cb3c2bf..4ddfbea0 100644 --- a/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart +++ b/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart @@ -77,9 +77,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class MultiProvider extends StatelessWidget { /// {@macro multi_provider} const MultiProvider({ - required this.repositoryProviders, - required this.blocProviders, required this.child, + this.repositoryProviders = const >[], + this.blocProviders = const [], super.key, }); @@ -88,11 +88,31 @@ class MultiProvider extends StatelessWidget { final Widget child; @override - Widget build(BuildContext context) => MultiRepositoryProvider( - providers: repositoryProviders, - child: MultiBlocProvider( - providers: blocProviders, - child: child, - ), + Widget build(BuildContext context) { + if (repositoryProviders.isEmpty && blocProviders.isEmpty) { + return child; + } + + if (repositoryProviders.isEmpty) { + return MultiBlocProvider( + providers: blocProviders, + child: child, ); + } + + if (blocProviders.isEmpty) { + return MultiRepositoryProvider( + providers: repositoryProviders, + child: child, + ); + } + + return MultiRepositoryProvider( + providers: repositoryProviders, + child: MultiBlocProvider( + providers: blocProviders, + child: child, + ), + ); + } } diff --git a/packages/wyatt_bloc_helper/pubspec.yaml b/packages/wyatt_bloc_helper/pubspec.yaml index 00af1bf5..a133308c 100644 --- a/packages/wyatt_bloc_helper/pubspec.yaml +++ b/packages/wyatt_bloc_helper/pubspec.yaml @@ -6,20 +6,18 @@ version: 2.0.0 publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: - sdk: '>=2.17.0 <3.0.0' + sdk: ">=2.17.0 <3.0.0" dependencies: - flutter: - sdk: flutter - + flutter: { sdk: flutter } + flutter_bloc: ^8.1.1 equatable: ^2.0.5 dev_dependencies: - flutter_test: - sdk: flutter + flutter_test: { sdk: flutter } bloc_test: ^9.1.0 - + wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub - version: ^2.4.1 \ No newline at end of file + version: ^2.4.1 diff --git a/packages/wyatt_bloc_layout/.gitignore b/packages/wyatt_bloc_layout/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_bloc_layout/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_bloc_layout/.gitignore b/packages/wyatt_bloc_layout/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_bloc_layout/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/.pubignore b/packages/wyatt_bloc_layout/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_bloc_layout/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/AUTHORS b/packages/wyatt_bloc_layout/AUTHORS deleted file mode 100644 index f9506138..00000000 --- a/packages/wyatt_bloc_layout/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/AUTHORS b/packages/wyatt_bloc_layout/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_bloc_layout/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/LICENSE b/packages/wyatt_bloc_layout/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_bloc_layout/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/LICENSE b/packages/wyatt_bloc_layout/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_bloc_layout/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_bloc_layout/README.md b/packages/wyatt_bloc_layout/README.md index b31892df..39b4c134 100644 --- a/packages/wyatt_bloc_layout/README.md +++ b/packages/wyatt_bloc_layout/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,57 +16,46 @@ * along with this program. If not, see . --> -# Flutter - Wyatt Bloc Layout +# Wyatt Bloc Layout

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Flutter

Bloc Layout for Flutter. -Wyatt Bloc Layout is a Flutter package that builds on the Wyatt UI Layout package and the Wyatt Bloc Helper package. It provides a way to link multiple packages in order to create intelligent layouts that combine both layout and logic. The package allows developers to use the available layouts in the Wyatt UI Layout package along with the block state logic available in the Wyatt Bloc Helper package. It also uses the Wyatt Crud Bloc package to make it easier to implement CRUD logic. +Wyatt Bloc Layout is a Flutter package that is built on the Wyatt UI Layout package and the Wyatt Bloc Helper package. + +It provides a way to link multiple packages in order to create intelligent layouts that combine both layout and logic. The package allows developers to use the available layouts in the Wyatt UI Layout package along with the block state logic available in the Wyatt Bloc Helper package. + +It also uses the Wyatt Crud Bloc package to make it easier to implement CRUD logic. ### Features -- Allows developers to use available layouts from Wyatt UI Layout package. -- Links with the Wyatt Bloc Helper package to combine layout and block state logic. -- Uses the Wyatt Crud Bloc package to easily implement CRUD logic. +* Allows developers to use available layouts from Wyatt UI Layout package. +* Links with the Wyatt Bloc Helper package to combine layout and block state logic. +* Uses the Wyatt Crud Bloc package to easily implement CRUD logic. #### Available bloc layouts -- BottomNavigationBarGridLayoutCubitScreenCrudList -- BottomNavigationBarLayoutCubitScreen -- BottomNavigationBarLayoutCubitScreenCrud -- BottomNavigationBarLayoutCubitScreenCrudItem -- BottomNavigationBarLayoutCubitScreenCrudList -- FrameGridLayoutCubitScreenCrudList -- FrameLayoutCubitScreen -- FrameLayoutCubitScreenCrud -- FrameLayoutCubitScreenCrudItem -- FrameLayoutCubitScreenCrudList -- TopAppBarGridLayoutCubitScreenCrudList -- TopAppBarLayoutCubitScreen -- TopAppBarLayoutCubitScreenCrud -- TopAppBarLayoutCubitScreenCrudItem -- TopAppBarLayoutCubitScreenCrudList -- TopNavigationBarGridLayoutCubitScreenCrudList -- TopNavigationBarLayoutCubitScreen -- TopNavigationBarLayoutCubitScreenCrud -- TopNavigationBarLayoutCubitScreenCrudItem -- TopNavigationBarLayoutCubitScreenCrudList - -### Installation - -To use Wyatt Bloc Layout in your Flutter project, add the following dependency to your pubspec.yaml file: - -```yaml -wyatt_bloc_layout: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_bloc_layout -``` - -Then, run flutter pub get to download the package. +* BottomNavigationBarGridLayoutCubitScreenCrudList +* BottomNavigationBarLayoutCubitScreen +* BottomNavigationBarLayoutCubitScreenCrud +* BottomNavigationBarLayoutCubitScreenCrudItem +* BottomNavigationBarLayoutCubitScreenCrudList +* FrameGridLayoutCubitScreenCrudList +* FrameLayoutCubitScreen +* FrameLayoutCubitScreenCrud +* FrameLayoutCubitScreenCrudItem +* FrameLayoutCubitScreenCrudList +* TopAppBarGridLayoutCubitScreenCrudList +* TopAppBarLayoutCubitScreen +* TopAppBarLayoutCubitScreenCrud +* TopAppBarLayoutCubitScreenCrudItem +* TopAppBarLayoutCubitScreenCrudList +* TopNavigationBarGridLayoutCubitScreenCrudList +* TopNavigationBarLayoutCubitScreen +* TopNavigationBarLayoutCubitScreenCrud +* TopNavigationBarLayoutCubitScreenCrudItem +* TopNavigationBarLayoutCubitScreenCrudList diff --git a/packages/wyatt_bloc_layout/analysis_options.yaml b/packages/wyatt_bloc_layout/analysis_options.yaml index 90d6bd51..8c9daa4e 100644 --- a/packages/wyatt_bloc_layout/analysis_options.yaml +++ b/packages/wyatt_bloc_layout/analysis_options.yaml @@ -1,17 +1 @@ -# Copyright (C) 2023 WYATT GROUP -# Please see the AUTHORS file for details. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - include: package:wyatt_analysis/analysis_options.flutter.yaml diff --git a/packages/wyatt_bloc_layout/example/lib/bloc/example_cubit.dart b/packages/wyatt_bloc_layout/example/lib/bloc/example_cubit.dart index 80c20d1a..dd2275d4 100644 --- a/packages/wyatt_bloc_layout/example/lib/bloc/example_cubit.dart +++ b/packages/wyatt_bloc_layout/example/lib/bloc/example_cubit.dart @@ -1,27 +1,28 @@ import 'dart:async'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; class ExampleCubit extends Cubit { - ExampleCubit() : super(CrudInitial()); + ExampleCubit() : super(const CrudInitial()); FutureOr run() async { while (true) { await Future.delayed(const Duration(seconds: 1)); - emit(CrudLoading()); + emit(const CrudLoading()); await Future.delayed(const Duration(seconds: 1)); emit(const CrudError('Cubit Error')); await Future.delayed(const Duration(seconds: 1)); emit(const CrudLoaded('DATA LOADED')); await Future.delayed(const Duration(seconds: 1)); - emit(CrudInitial()); + emit(const CrudInitial()); } } FutureOr runList() async { while (true) { await Future.delayed(const Duration(seconds: 1)); - emit(CrudLoading()); + emit(const CrudLoading()); await Future.delayed(const Duration(seconds: 1)); emit(const CrudError('Cubit Error')); await Future.delayed(const Duration(seconds: 1)); @@ -34,7 +35,7 @@ class ExampleCubit extends Cubit { ]), ); await Future.delayed(const Duration(seconds: 1)); - emit(CrudInitial()); + emit(const CrudInitial()); } } } diff --git a/packages/wyatt_bloc_layout/example/lib/components/custom_app_bar.dart b/packages/wyatt_bloc_layout/example/lib/components/custom_app_bar.dart index aff474a8..1ca3cab4 100644 --- a/packages/wyatt_bloc_layout/example/lib/components/custom_app_bar.dart +++ b/packages/wyatt_bloc_layout/example/lib/components/custom_app_bar.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; part 'custom_app_bar.g.dart'; diff --git a/packages/wyatt_bloc_layout/example/lib/components/custom_bottom_bar.dart b/packages/wyatt_bloc_layout/example/lib/components/custom_bottom_bar.dart index 1b094adf..34417c03 100644 --- a/packages/wyatt_bloc_layout/example/lib/components/custom_bottom_bar.dart +++ b/packages/wyatt_bloc_layout/example/lib/components/custom_bottom_bar.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; part 'custom_bottom_bar.g.dart'; diff --git a/packages/wyatt_bloc_layout/example/lib/components/custom_error_widget.dart b/packages/wyatt_bloc_layout/example/lib/components/custom_error_widget.dart index 77364998..5d9cfee7 100644 --- a/packages/wyatt_bloc_layout/example/lib/components/custom_error_widget.dart +++ b/packages/wyatt_bloc_layout/example/lib/components/custom_error_widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; part 'custom_error_widget.g.dart'; diff --git a/packages/wyatt_bloc_layout/example/lib/components/custom_loading_widget.dart b/packages/wyatt_bloc_layout/example/lib/components/custom_loading_widget.dart index 94517557..fe53a631 100644 --- a/packages/wyatt_bloc_layout/example/lib/components/custom_loading_widget.dart +++ b/packages/wyatt_bloc_layout/example/lib/components/custom_loading_widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; part 'custom_loading_widget.g.dart'; diff --git a/packages/wyatt_bloc_layout/example/lib/components/theme_components.dart b/packages/wyatt_bloc_layout/example/lib/components/theme_components.dart index b0b1f404..afc4203d 100644 --- a/packages/wyatt_bloc_layout/example/lib/components/theme_components.dart +++ b/packages/wyatt_bloc_layout/example/lib/components/theme_components.dart @@ -2,7 +2,7 @@ import 'package:bloc_layout_example/components/custom_app_bar.dart'; import 'package:bloc_layout_example/components/custom_bottom_bar.dart'; import 'package:bloc_layout_example/components/custom_error_widget.dart'; import 'package:bloc_layout_example/components/custom_loading_widget.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; class AppThemeComponent { static ComponentThemeData get components => ComponentThemeData.raw( diff --git a/packages/wyatt_bloc_layout/example/lib/main.dart b/packages/wyatt_bloc_layout/example/lib/main.dart index 4542215e..2856aec7 100644 --- a/packages/wyatt_bloc_layout/example/lib/main.dart +++ b/packages/wyatt_bloc_layout/example/lib/main.dart @@ -17,7 +17,10 @@ import 'package:bloc_layout_example/bloc/example_cubit.dart'; import 'package:bloc_layout_example/components/theme_components.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; void main() { runApp(const MyApp()); diff --git a/packages/wyatt_bloc_layout/example/pubspec.yaml b/packages/wyatt_bloc_layout/example/pubspec.yaml index 50944ac6..8d19be75 100644 --- a/packages/wyatt_bloc_layout/example/pubspec.yaml +++ b/packages/wyatt_bloc_layout/example/pubspec.yaml @@ -30,9 +30,27 @@ dependencies: flutter: sdk: flutter + flutter_bloc: ^8.1.2 + wyatt_bloc_layout: path: "../" + wyatt_bloc_helper: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.0.0 + + wyatt_ui_layout: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 + + wyatt_crud_bloc: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.1.0+2 + + wyatt_ui_components: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 + wyatt_component_copy_with_extension: git: url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git diff --git a/packages/wyatt_bloc_layout/lib/src/core/mixins/gird_view_mixin.dart b/packages/wyatt_bloc_layout/lib/src/core/mixins/gird_view_mixin.dart index 696ae8e9..636048e2 100644 --- a/packages/wyatt_bloc_layout/lib/src/core/mixins/gird_view_mixin.dart +++ b/packages/wyatt_bloc_layout/lib/src/core/mixins/gird_view_mixin.dart @@ -15,7 +15,8 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; +import 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; mixin GridLayoutMixin { Widget gridChild(BuildContext context, SuccessType? successType); diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_grid_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_grid_layout_cubit_screen_crud_list.dart index 099d6b79..952a2c81 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_grid_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_grid_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class BottomNavigationBarGridLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen.dart b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen.dart index c729a0f6..0a02294f 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen.dart @@ -18,6 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; abstract class BottomNavigationBarLayoutCubitScreen< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud.dart b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud.dart index 16cc1abf..c1cc938d 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud.dart @@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class BottomNavigationBarLayoutCubitScreenCrud< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_item.dart b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_item.dart index f2bbdb07..69ff4371 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_item.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_item.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class BottomNavigationBarLayoutCubitScreenCrudItem< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_list.dart index cce7f2a4..7c6c5b21 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/bottom_navigation_bar_bloc_layout/bottom_navigation_bar_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class BottomNavigationBarLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_base.dart b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_base.dart index b4848316..4dc4107a 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_base.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_base.dart @@ -15,7 +15,7 @@ // along with this program. If not, see . import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; -import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; abstract class CubitScreenBase, State extends Object> extends CubitScreen { diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_base.dart b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_base.dart index a113c5ad..ad9142f8 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_base.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_base.dart @@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class CubitScreenCrudBase, CrudSuccessState extends CrudSuccess> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_item_base.dart b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_item_base.dart index 5e81a799..3fe2becb 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_item_base.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_item_base.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class CubitScreenCrudItemBase, T extends Object?> extends CubitScreenCrudBase> { diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_list_base.dart b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_list_base.dart index d641b6b5..f886138e 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_list_base.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/cubit_screen_crud_list_base.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class CubitScreenCrudListBase, T extends Object?> extends CubitScreenCrudBase> { diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_grid_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_grid_layout_cubit_screen_crud_list.dart index e62fea8c..e54e5c49 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_grid_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_grid_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class FrameLayoutGridCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen.dart b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen.dart index d8631d8e..51985223 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen.dart @@ -18,6 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; abstract class FrameLayoutCubitScreen, State extends Object> extends CubitScreenBase { diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud.dart b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud.dart index a498490b..62e5fc91 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud.dart @@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class FrameLayoutCubitScreenCrud< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_item.dart b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_item.dart index 92db37fa..80381609 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_item.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_item.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class FrameLayoutCubitScreenCrudItem< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_list.dart index 8c38994a..6bbf7a6b 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/frame_bloc_layout/frame_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class FrameLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/grid_cubit_screen_crud_list_base.dart b/packages/wyatt_bloc_layout/lib/src/presentation/grid_cubit_screen_crud_list_base.dart index 28931c40..c95cb338 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/grid_cubit_screen_crud_list_base.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/grid_cubit_screen_crud_list_base.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class GridCubitScreenCrudListBase< Cubit extends bloc_base.Cubit, T extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_grid_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_grid_layout_cubit_screen_crud_list.dart index efc7ecdc..e20a1842 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_grid_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_grid_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopAppBarGridLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen.dart index 80479742..48fe0abe 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen.dart @@ -18,6 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; abstract class TopAppBarLayoutCubitScreen, State extends Object> extends CubitScreenBase { diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud.dart index 1de4081a..efa82d3e 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud.dart @@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopAppBarLayoutCubitScreenCrud< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_item.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_item.dart index 9e90c286..dd7e2bb1 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_item.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_item.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopAppBarLayoutCubitScreenCrudItem< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_list.dart index 9bc6047d..902ce24c 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_app_bar_bloc_layout/top_app_bar_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopAppBarLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_grid_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_grid_layout_cubit_screen_crud_list.dart index 238079ba..b57d29cf 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_grid_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_grid_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopNavigationBarGridLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen.dart index 7978b76f..b1903cdc 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen.dart @@ -18,6 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +import 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; abstract class TopNavigationBarLayoutCubitScreen< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud.dart index 65bd7bff..76bd6beb 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud.dart @@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopNavigationBarLayoutCubitScreenCrud< Cubit extends bloc_base.Cubit, diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_item.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_item.dart index 6b4c022b..112b8844 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_item.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_item.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopNavigationBarLayoutCubitScreenCrudItem< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_list.dart b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_list.dart index 0b04c6f2..0f17b282 100644 --- a/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_list.dart +++ b/packages/wyatt_bloc_layout/lib/src/presentation/top_navigation_bar_bloc_layout/top_navigation_bar_layout_cubit_screen_crud_list.dart @@ -16,6 +16,7 @@ import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base; import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart'; +import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; abstract class TopNavigationBarLayoutCubitScreenCrudList< Cubit extends bloc_base.Cubit, SuccessType extends Object?> diff --git a/packages/wyatt_bloc_layout/lib/src/src.dart b/packages/wyatt_bloc_layout/lib/src/src.dart index 4da50dac..d35a3ae0 100644 --- a/packages/wyatt_bloc_layout/lib/src/src.dart +++ b/packages/wyatt_bloc_layout/lib/src/src.dart @@ -14,11 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'package:flutter_bloc/flutter_bloc.dart'; -export 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; -export 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; -export 'package:wyatt_ui_components/wyatt_ui_components.dart'; -export 'package:wyatt_ui_layout/wyatt_ui_layout.dart'; - export 'core/core.dart'; export 'presentation/presentation.dart'; diff --git a/packages/wyatt_bloc_layout/pubspec.yaml b/packages/wyatt_bloc_layout/pubspec.yaml index 11e03807..538ebf97 100644 --- a/packages/wyatt_bloc_layout/pubspec.yaml +++ b/packages/wyatt_bloc_layout/pubspec.yaml @@ -3,43 +3,35 @@ description: Layouts based on bloc helper library repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_bloc_layout version: 0.0.1 -publish_to: "none" +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: sdk: ">=2.17.0 <3.0.0" dependencies: - flutter: - sdk: flutter - + flutter: { sdk: flutter } + flutter_bloc: ^8.1.2 wyatt_bloc_helper: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_bloc_helper + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.0.0 wyatt_ui_layout: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_ui_layout + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 wyatt_crud_bloc: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_crud_bloc + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.1.0+2 wyatt_ui_components: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_ui_components + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 dev_dependencies: - flutter_test: - sdk: flutter + flutter_test: { sdk: flutter } wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.4.1 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.4.1 diff --git a/packages/wyatt_component_copy_with_extension/.gitignore b/packages/wyatt_component_copy_with_extension/.gitignore deleted file mode 100644 index 3cceda55..00000000 --- a/packages/wyatt_component_copy_with_extension/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ - -# Avoid committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_component_copy_with_extension/.gitignore b/packages/wyatt_component_copy_with_extension/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_component_copy_with_extension/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_extension/.pubignore b/packages/wyatt_component_copy_with_extension/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_component_copy_with_extension/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_extension/AUTHORS b/packages/wyatt_component_copy_with_extension/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_component_copy_with_extension/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_extension/LICENSE b/packages/wyatt_component_copy_with_extension/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_component_copy_with_extension/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_extension/README.md b/packages/wyatt_component_copy_with_extension/README.md index 3ef1d24d..4dd5beaf 100644 --- a/packages/wyatt_component_copy_with_extension/README.md +++ b/packages/wyatt_component_copy_with_extension/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. * - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,15 +16,32 @@ * along with this program. If not, see . --> -# Flutter - Component Copy With Extension +# Component Copy With Extension

Style: Wyatt Analysis - SDK: Flutter + SDK: Dart & Flutter

This package provides annotations for generating code and simplifying the use of an UI kit within a Flutter application. **The package contains only the annotation classes**. +> This package does not contain Flutter specific code, but there is no sense in using it without Flutter. + +## Summary + +* `ComponentProxyExtension` - Annotation class for generating a proxy of a component of an UI kit. +* `ComponentCopyWithExtension` - Annotation class for generating the copyWith method of a component implementation. + +For example, let's say we have a component of an UI kit that we want to use in our application. + +1) We create the component in the `wyatt_ui_components` , add the `ComponentProxyExtension` annotation and generate the code. This component does not have any specific implementation, and only have a set of properties. +2) Now we implement the component in our ui kit, `wyatt_ui_kit` , add the `ComponentCopyWithExtension` annotation and generate the code. This component has a specific implementation and can be used in the application. +3) But we can implement multiple ui kits, and each of them can have their own implementation of the same component. And at the top of the application tree we can use the `wyatt_ui_components` package, which contains only the proxy of the component. + +> In that way, the **application is UI kit agnostic**, and we can easily change the UI kit without changing the code of the application. + +We will use the `LoaderComponent` component as an example in this documentation. + ## Annotation Classes #### `ComponentProxyExtension` @@ -32,31 +49,30 @@ This package provides annotations for generating code and simplifying the use of This annotation class is used to annotate a new component of an UI kit in the `wyatt_ui_components` package. It generates the abstract proxy of the component and allows access to all its properties in different packages and throughout the application. ```dart -part 'text_field_component.g.dart'; +part 'loader_component.g.dart'; @ComponentProxyExtension() -abstract class TextFieldComponent extends Component { - with CopyWithMixin<$TextFieldComponentCWProxy> { - - const TextFieldComponent({ - ... +abstract class LoaderComponent extends Component + with CopyWithMixin<$LoaderComponentCWProxy> { + + const LoaderComponent({ + ... }); } ``` #### `ComponentCopyWithExtension` -This annotation class is used to annotate the implementation of components directly in the application. It generates the implementation of the proxy and the mixin to ensure that the component meets the specifications defined in the `wyatt_ui_components package`. +This annotation class is used to annotate the implementation of components directly in the application. It generates the implementation of the proxy and the mixin to ensure that the component meets the specifications defined in the `wyatt_ui_components package` . ```dart -part 'text_field_component.g.dart'; +part 'loader.g.dart'; -@ComponentProxyExtension() -abstract class TextFieldComponent extends Component { - with CopyWithMixin<$TextFieldComponentCWProxy> { - - const TextFieldComponent({ - ... +@ComponentCopyWithExtension() +class Loader extends LoaderComponent with $LoaderCWMixin { + + const Loader({ + ... }); } ``` diff --git a/packages/wyatt_component_copy_with_extension/analysis_options.yaml b/packages/wyatt_component_copy_with_extension/analysis_options.yaml index 0939257e..1c320a71 100644 --- a/packages/wyatt_component_copy_with_extension/analysis_options.yaml +++ b/packages/wyatt_component_copy_with_extension/analysis_options.yaml @@ -1,5 +1,5 @@ -include: package:wyatt_analysis/analysis_options.flutter.yaml +include: package:wyatt_analysis/analysis_options.yaml diff --git a/packages/wyatt_component_copy_with_extension/lib/src/component_copy_with_extension.dart b/packages/wyatt_component_copy_with_extension/lib/src/component_copy_with_extension.dart index 482b1748..a71e23bf 100644 --- a/packages/wyatt_component_copy_with_extension/lib/src/component_copy_with_extension.dart +++ b/packages/wyatt_component_copy_with_extension/lib/src/component_copy_with_extension.dart @@ -17,9 +17,29 @@ import 'package:meta/meta_meta.dart'; import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart'; -/// Annotation used to indicate that the `copyWith` extension -/// should be generated for the compononent. +/// {@template component_copy_with_extension} +/// This annotation class is used to annotate the implementation of components +/// directly in the application. It generates the implementation of the proxy +/// and the mixin to ensure that the component meets the specifications +/// defined in the UI Kit. +/// +/// Basically it indicate that the `copyWith` extension +/// should be generated for the component. +/// +/// ```dart +/// part 'loader.g.dart'; +/// +/// @ComponentCopyWithExtension() +/// class Loader extends LoaderComponent with $LoaderCWMixin { +/// +/// const Loader({ +/// ... +/// }); +/// } +/// ``` +/// {@endtemplate} @Target({TargetKind.classType}) class ComponentCopyWithExtension extends ComponentAnnotation { + /// {@macro component_copy_with_extension} const ComponentCopyWithExtension({super.skipFields}); } diff --git a/packages/wyatt_component_copy_with_extension/lib/src/component_proxy_extension.dart b/packages/wyatt_component_copy_with_extension/lib/src/component_proxy_extension.dart index 3e75eef5..d34ac82c 100644 --- a/packages/wyatt_component_copy_with_extension/lib/src/component_proxy_extension.dart +++ b/packages/wyatt_component_copy_with_extension/lib/src/component_proxy_extension.dart @@ -14,12 +14,32 @@ // along with this program. If not, see . import 'package:meta/meta_meta.dart'; +import 'package:wyatt_component_copy_with_extension/src/domain/component_annotation.dart'; +/// {@template component_proxy_extension} +/// This annotation class is used to annotate a new component of an UI kit. +/// It generates the abstract proxy of the component and allows access to +/// all its properties in different packages and throughout the application. +/// +/// ```dart +/// part 'loader_component.g.dart'; +/// +/// @ComponentProxyExtension() +/// abstract class LoaderComponent extends Component +/// with CopyWithMixin<$LoaderComponentCWProxy> { +/// +/// const LoaderComponent({ +/// ... +/// }); +/// } +/// ``` +/// +/// The [skipFields] option allows you to directly and specifically change +/// a field. This makes it easier to use. +/// +/// {@endtemplate} @Target({TargetKind.classType}) -class ComponentProxyExtension { - const ComponentProxyExtension({ - this.skipFields = true, - }); - - final bool? skipFields; +class ComponentProxyExtension extends ComponentAnnotation { + /// {@macro component_proxy_extension} + const ComponentProxyExtension({super.skipFields}); } diff --git a/packages/wyatt_component_copy_with_extension/lib/src/domain/component_annotation.dart b/packages/wyatt_component_copy_with_extension/lib/src/domain/component_annotation.dart index 1faf6119..4408aa19 100644 --- a/packages/wyatt_component_copy_with_extension/lib/src/domain/component_annotation.dart +++ b/packages/wyatt_component_copy_with_extension/lib/src/domain/component_annotation.dart @@ -14,7 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template component_annotation} +/// Abstract class that is used as a base for all annotations +/// {@endtemplate} abstract class ComponentAnnotation { + /// {@macro component_annotation} const ComponentAnnotation({this.skipFields = true}); /// Prevent the library from generating `copyWith` functions for individual diff --git a/packages/wyatt_component_copy_with_extension/pubspec.yaml b/packages/wyatt_component_copy_with_extension/pubspec.yaml index de13dc2d..4b0375c5 100644 --- a/packages/wyatt_component_copy_with_extension/pubspec.yaml +++ b/packages/wyatt_component_copy_with_extension/pubspec.yaml @@ -3,18 +3,15 @@ description: Extension for component copy with feature. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/component_copy_with_extension version: 1.0.0 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: sdk: ">=2.19.0 <3.0.0" dependencies: meta: ^1.8.0 - path: ^1.8.0 dev_dependencies: wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub version: ^2.4.1 - -# The following section is specific to Flutter. -flutter: - uses-material-design: true diff --git a/packages/wyatt_component_copy_with_gen/.gitignore b/packages/wyatt_component_copy_with_gen/.gitignore deleted file mode 100644 index 3cceda55..00000000 --- a/packages/wyatt_component_copy_with_gen/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ - -# Avoid committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_component_copy_with_gen/.gitignore b/packages/wyatt_component_copy_with_gen/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_component_copy_with_gen/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_gen/.pubignore b/packages/wyatt_component_copy_with_gen/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_component_copy_with_gen/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_gen/AUTHORS b/packages/wyatt_component_copy_with_gen/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_component_copy_with_gen/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_gen/LICENSE b/packages/wyatt_component_copy_with_gen/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_component_copy_with_gen/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_component_copy_with_gen/README.md b/packages/wyatt_component_copy_with_gen/README.md index 6b606cd8..64e5e799 100644 --- a/packages/wyatt_component_copy_with_gen/README.md +++ b/packages/wyatt_component_copy_with_gen/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. * - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,30 +16,32 @@ * along with this program. If not, see . --> -# Dart - Component Copy With Gen +# Component Copy With Gen

Style: Wyatt Analysis SDK: Dart & Flutter

-A Dart package for generating code from annotations to ease the use of a UIKit in Flutter applications. The generated code is based on the annotation classes present in the 'wyatt_component_copy_with_extension' package. +A Dart package for generating code from annotations to ease the use of a UIKit in Flutter applications. The generated code is based on the annotation classes present in the [ `wyatt_component_copy_with_extension` package](https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_component_copy_with_extension) + +> This package does not contain Flutter specific code, but there is no sense in using it without Flutter. ## Features -- Supports the generation of abstract proxies in the `wyatt_ui_components` package. -- Supports direct use in Flutter applications. +* Supports the generation of abstract proxies in the `wyatt_ui_components` package. +* Supports direct use in Flutter applications. ## Usage ### In the 'wyatt_ui_components' package -- Add the appropriate annotation when addicdng a new component. -- Run the build runner command to generate the proxy. +* Add the appropriate annotation when adding a new component. +* Run the build runner command to generate the proxy. -### In Flutter applications +### In Flutter applications (or UI Kit implementations) -- Add the following dependencies to your pubspec.yaml: +* Add the following dependencies to your pubspec.yaml: ```yaml dependencies: @@ -51,7 +53,7 @@ dev_dependencies: build_runner: ^2.3.3 ``` -- In your UIKit, extend the desired component class and add the appropriate annotation. -- Run the code generation command via the build runner. +* In your UIKit, extend the desired component class and add the appropriate annotation. +* Run the code generation command via the build runner. For further details and additional features on class annotation, see the 'wyatt_component_copy_with_extension' package's README. diff --git a/packages/wyatt_component_copy_with_gen/pubspec.yaml b/packages/wyatt_component_copy_with_gen/pubspec.yaml index bae83cb0..301cb28c 100644 --- a/packages/wyatt_component_copy_with_gen/pubspec.yaml +++ b/packages/wyatt_component_copy_with_gen/pubspec.yaml @@ -3,21 +3,19 @@ description: Generator for copywith method for components. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/component_copy_with_gen version: 1.0.0 -publish_to: "none" +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: sdk: ">=2.19.0 <3.0.0" dependencies: - path: ^1.8.0 build: ^2.3.1 source_gen: ^1.2.7 analyzer: ^5.4.0 wyatt_component_copy_with_extension: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_component_copy_with_extension + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^1.0.0 dev_dependencies: test: ^1.21.0 diff --git a/packages/wyatt_crud_bloc/.gitignore b/packages/wyatt_crud_bloc/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_crud_bloc/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_crud_bloc/.gitignore b/packages/wyatt_crud_bloc/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_crud_bloc/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/.pubignore b/packages/wyatt_crud_bloc/.pubignore deleted file mode 100644 index 4ad4d99b..00000000 --- a/packages/wyatt_crud_bloc/.pubignore +++ /dev/null @@ -1,2 +0,0 @@ -google-services.json -.vscode \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/.pubignore b/packages/wyatt_crud_bloc/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_crud_bloc/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/AUTHORS b/packages/wyatt_crud_bloc/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_crud_bloc/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/LICENSE b/packages/wyatt_crud_bloc/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_crud_bloc/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/LICENSE b/packages/wyatt_crud_bloc/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_crud_bloc/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_crud_bloc/README.md b/packages/wyatt_crud_bloc/README.md index 8b55e735..4f483186 100644 --- a/packages/wyatt_crud_bloc/README.md +++ b/packages/wyatt_crud_bloc/README.md @@ -1,39 +1,167 @@ - -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. +# CRUD BloC -## Features +

+ Style: Wyatt Analysis + SDK: Flutter +

-TODO: List what your package can do. Maybe include images, gifs, or videos. +CRUD Bloc Pattern utilities for Flutter. -## Getting started +This package defines a set of classes that can be used to implement the CRUD Bloc Pattern. -TODO: List prerequisites and provide or point to information on how to -start using the package. +* Model +* Data Source + + In Memory + + Firestore +* Repository +* Use Case + + Create + + Get + + Get All + + Update + + Update All + + Delete + + Delete All + + Query +* Bloc + + Standard (C R U D), you have to choose the responsiblity of the bloc for each use case. For example, you can have a cubit that only handles the creation of an entity, and another cubit that only handles the deletion of an entity. Each cubit can only have one operation responsibility of each type, for example you can't have a cubit that handles get and get all. + + Advanced, you can set every use case to be handled by the bloc. This is useful if you want to have a single bloc that handles all the operations of an entity. ## Usage -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. +Create a model class that extends the `ObjectModel` class. ```dart -const like = 'sample'; +class User extends ObjectModel { + @override + final String? id; + + final String? name; + + const User({ + required this.name, + this.id, + }); + + Map toMap() { + return { + 'name': name ?? '', + }; + } + + @override + String toString() => 'User(id: $id, name: $name)'; +} ``` -## Additional information +You have to implement a bloc. -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +```dart +/// A [CrudCubit] for [User]. +class UserCubit extends CrudCubit { + final CrudRepository _crudRepository; + + UserCubit(this._crudRepository); + + @override + CreateOperation? get createOperation => + Create(_crudRepository); + + @override + DeleteOperation? get deleteOperation => + Delete(_crudRepository); + + @override + ReadOperation? get readOperation => + GetAll(_crudRepository); + + @override + UpdateOperation? get updateOperation => + Update(_crudRepository); +} +``` + +> You can also use the `CrudAdvancedCubit` class to implement a bloc that handles all the use cases. + +Then you can use the bloc in your widget with a data source and a repository. + +```dart +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + final CrudDataSource userLocalDataSource = + CrudInMemoryDataSourceImpl(toMap: (user) => user.toMap()); + + final CrudRepository userRepository = + CrudRepositoryImpl(crudDataSource: userLocalDataSource); + + return RepositoryProvider>.value( + value: userRepository, + child: BlocProvider( + create: (context) => UserCubit(userRepository)..read(), + child: MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(), + ), + ), + ); + } +} +``` + +And anywhere in your widget tree you can use the BlocBuilder to build your widget. + +```dart +... +BlocBuilder( + builder: (context, state) { + return CrudBuilder.typed>( + state: state, + builder: ((context, state) { + return ListView.builder( + shrinkWrap: true, + itemCount: state.data.length, + itemBuilder: (context, index) { + final user = state.data.elementAt(index); + return ListTile( + title: Text(user?.name ?? 'Error'), + subtitle: Text(user?.id ?? 'Error'), + onTap: () { + context.read().delete(id: (user?.id)!); + }, + ); + }, + ); + }), + initialBuilder: (context, state) => const Text("Loading..."), + loadingBuilder: (context, state) => const Text("Loading..."), + errorBuilder: (context, state) => Text("Error: $state"), + ); + }, +), +... +``` diff --git a/packages/wyatt_crud_bloc/analysis_options.yaml b/packages/wyatt_crud_bloc/analysis_options.yaml index f09fbccc..8c9daa4e 100644 --- a/packages/wyatt_crud_bloc/analysis_options.yaml +++ b/packages/wyatt_crud_bloc/analysis_options.yaml @@ -1,4 +1 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml - -analyzer: - exclude: "!example/**" diff --git a/packages/wyatt_crud_bloc/example/lib/app.dart b/packages/wyatt_crud_bloc/example/lib/app.dart index 47d7e59e..d5339343 100644 --- a/packages/wyatt_crud_bloc/example/lib/app.dart +++ b/packages/wyatt_crud_bloc/example/lib/app.dart @@ -36,8 +36,12 @@ class MyApp extends StatelessWidget { return RepositoryProvider>.value( value: userRepository, - child: BlocProvider( - create: (context) => UserCubit(userRepository)..getAll(), + child: MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => UserCubit(userRepository)..read(), + ), + ], child: MaterialApp( title: 'Flutter Demo', theme: ThemeData( @@ -78,9 +82,7 @@ class MyHomePage extends StatelessWidget { title: Text(user?.name ?? 'Error'), subtitle: Text(user?.id ?? 'Error'), onTap: () { - context.read().delete( - (user?.id)!, - ); + context.read().delete(id: (user?.id)!); }, ); }, @@ -108,22 +110,10 @@ class MyHomePage extends StatelessWidget { ), ElevatedButton( onPressed: () { - context.read().deleteAll(); - }, - child: const Text("DeleteAll"), - ), - ElevatedButton( - onPressed: () { - context.read().getAll(); + context.read().read(); }, child: const Text("GetAll"), ), - ElevatedButton( - onPressed: () { - context.read().query([LimitQuery(2)]); - }, - child: const Text("Query"), - ), const SizedBox(height: 20), ], ), diff --git a/packages/wyatt_crud_bloc/example/lib/models.dart b/packages/wyatt_crud_bloc/example/lib/models.dart index b4ccfebf..e9ed1c7f 100644 --- a/packages/wyatt_crud_bloc/example/lib/models.dart +++ b/packages/wyatt_crud_bloc/example/lib/models.dart @@ -18,37 +18,18 @@ import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; class User extends ObjectModel { @override - String? id; + final String? id; - String? name; - String? email; - String? phone; + final String? name; + final String? email; + final String? phone; - User({ + const User({ required this.name, required this.email, required this.phone, this.id, }); - // User._(); - - // factory User.parser() { - // return User._(); - // } - - // @override - // User? from(DocumentSnapshot? object) { - // if (object == null) return null; - // if (object.exists) { - // return User( - // id: object.id, - // name: (object.data() as Map?)!['name'] as String, - // email: (object.data() as Map?)!['email'] as String, - // phone: (object.data() as Map?)!['phone'] as String, - // ); - // } - // return null; - // } Map toMap() { return { diff --git a/packages/wyatt_crud_bloc/example/lib/user_cubit.dart b/packages/wyatt_crud_bloc/example/lib/user_cubit.dart index 703d6686..cc34df6c 100644 --- a/packages/wyatt_crud_bloc/example/lib/user_cubit.dart +++ b/packages/wyatt_crud_bloc/example/lib/user_cubit.dart @@ -17,32 +17,25 @@ import 'package:crud_bloc_example/models.dart'; import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart'; +/// A [CrudCubit] for [User]. class UserCubit extends CrudCubit { final CrudRepository _crudRepository; UserCubit(this._crudRepository); @override - Create? get crudCreate => Create(_crudRepository); + CreateOperation? get createOperation => + Create(_crudRepository); @override - Delete? get crudDelete => Delete(_crudRepository); + DeleteOperation? get deleteOperation => + Delete(_crudRepository); @override - DeleteAll? get crudDeleteAll => DeleteAll(_crudRepository); + ReadOperation? get readOperation => + GetAll(_crudRepository); @override - Get? get crudGet => Get(_crudRepository); - - @override - GetAll? get crudGetAll => GetAll(_crudRepository); - - @override - Query? get crudQuery => Query(_crudRepository); - - @override - Update? get crudUpdate => Update(_crudRepository); - - @override - UpdateAll? get crudUpdateAll => UpdateAll(_crudRepository); + UpdateOperation? get updateOperation => + Update(_crudRepository); } diff --git a/packages/wyatt_crud_bloc/lib/src/core/core.dart b/packages/wyatt_crud_bloc/lib/src/core/core.dart index 1d218692..12ebcadf 100644 --- a/packages/wyatt_crud_bloc/lib/src/core/core.dart +++ b/packages/wyatt_crud_bloc/lib/src/core/core.dart @@ -15,3 +15,4 @@ // along with this program. If not, see . export 'enums/where_query_type.dart'; +export 'mixins/operation.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart b/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart index f20879e7..6a7c9bfe 100644 --- a/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart +++ b/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines different query types for WhereQuery. enum WhereQueryType { isEqualTo, isNotEqualTo, diff --git a/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart b/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart new file mode 100644 index 00000000..dbfc08ff --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart @@ -0,0 +1,34 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; + +/// Defines every write operation in CRUD. +mixin CreateOperation + on AsyncUseCase {} + +/// Defines every read operation in CRUD. +mixin ReadOperation + on AsyncUseCase {} + +/// Defines every update operation in CRUD. +mixin UpdateOperation + on AsyncUseCase {} + +/// Defines every delete operation in CRUD. +mixin DeleteOperation + on AsyncUseCase {} diff --git a/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart index bb892251..7c2f706b 100644 --- a/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart +++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart @@ -17,13 +17,17 @@ import 'dart:async'; import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart'; -import 'package:wyatt_crud_bloc/src/core/extensions/num_extension.dart'; -import 'package:wyatt_crud_bloc/src/domain/data_sources/crud_data_source.dart'; +import 'package:wyatt_crud_bloc/src/domain/data_sources/data_sources.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +/// {@template crud_in_memory_data_source_impl} +/// A [CrudDataSource] that stores data in memory. +/// {@endtemplate} class CrudInMemoryDataSourceImpl extends CrudDataSource { + /// {@macro crud_in_memory_data_source_impl} CrudInMemoryDataSourceImpl({required this.toMap, Map? data}) : _data = data ?? {}; final Map _data; diff --git a/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart index e70ecc9c..2915f2e6 100644 --- a/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart +++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart @@ -20,15 +20,23 @@ import 'package:wyatt_crud_bloc/src/domain/data_sources/crud_data_source.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +/// {@template crud_firestore_data_source_impl} +/// A concrete implementation of [CrudDataSource] that uses +/// [FirebaseFirestore] as the data source. +/// {@endtemplate} class CrudFirestoreDataSourceImpl extends CrudDataSource { + /// {@macro crud_firestore_data_source_impl} CrudFirestoreDataSourceImpl( String collection, { + /// The function that converts a [DocumentSnapshot] to a [Model]. required Model Function( DocumentSnapshot>, SnapshotOptions?, ) fromFirestore, + + /// The function that converts a [Model] to a [Map]. required Map Function(Model, SetOptions?) toFirestore, FirebaseFirestore? firestore, }) : _firestore = firestore ?? FirebaseFirestore.instance, diff --git a/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart index f26fdc1d..7f068be2 100644 --- a/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart +++ b/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart @@ -21,9 +21,13 @@ import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +/// {@template crud_repository_impl} +/// A repository that implements the [CrudRepository] interface. +/// {@endtemplate} class CrudRepositoryImpl extends CrudRepository { - CrudRepositoryImpl({ + /// {@macro crud_repository_impl} + const CrudRepositoryImpl({ required CrudDataSource crudDataSource, }) : _crudDataSource = crudDataSource; final CrudDataSource _crudDataSource; @@ -99,6 +103,6 @@ class CrudRepositoryImpl if (lst.isNotNull) { return Ok, AppException>(lst); } - return Err, AppException>(ServerException()); + return Err, AppException>(const ServerException()); }); } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart index 95defb4c..b6d0ba30 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart @@ -17,27 +17,42 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +/// {@template crud_data_source} +/// A [BaseDataSource] that provides SCRUD operations. +/// {@endtemplate} abstract class CrudDataSource extends BaseDataSource { + /// {@macro crud_data_source} + const CrudDataSource(); + + /// Creates a new [Model] object. Future create(Model object, {String? id}); + /// Gets a [Model] object by its [id]. Future get(String id); + /// Gets all [Model] objects. Future> getAll(); + /// Updates a [Model] object by its [id]. Future update( String id, { Model? object, Map? raw, }); + /// Updates all [Model] objects. Future updateAll(Map? data); + /// Deletes a [Model] object by its [id]. Future delete(String id); + /// Deletes all [Model] objects. Future deleteAll(); + /// Queries [Model] objects by [conditions]. Future> query(List conditions); + /// Streams [Model] objects by [conditions]. Stream> stream({ String? id, List? conditions, diff --git a/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart b/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart index 2b419e41..10dc5a25 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart @@ -16,6 +16,13 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; +/// {@template object_model} +/// An abstract class that represents an object model. +/// {@endtemplate} abstract class ObjectModel extends Entity { + /// {@macro object_model} + const ObjectModel(); + + /// The id of the object model. String? get id; } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart b/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart index a414f3ff..5fe8908f 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart @@ -17,27 +17,59 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart'; -// ignore: one_member_abstracts -abstract class QueryParser { - Q parser(QueryInterface condition, Q query); +// // ignore: one_member_abstracts +// abstract class QueryParser { +// Q parser(QueryInterface condition, Q query); +// } + +typedef QueryParser = Q Function(QueryInterface condition, Q query); + +/// {@template query} +/// An abstract class that represents a query. +/// {@endtemplate} +abstract class QueryInterface extends Entity { + /// {@macro query} + const QueryInterface(); } -abstract class QueryInterface extends Entity {} - +/// {@template where_query} +/// Represents a where query. +/// {@endtemplate} class WhereQuery extends QueryInterface { - WhereQuery(this.type, this.field, this.value); + /// {@macro where_query} + const WhereQuery(this.type, this.field, this.value); + + /// The type of the where query. final WhereQueryType type; + + /// The field of the where query. final String field; + + /// The value of the where query. final Value value; } +/// {@template limit_query} +/// Represents a limit query. +/// {@endtemplate} class LimitQuery extends QueryInterface { - LimitQuery(this.limit); + /// {@macro limit_query} + const LimitQuery(this.limit); + + /// The limit of the limit query. final int limit; } +/// {@template offset_query} +/// Represents an offset query. +/// {@endtemplate} class OrderByQuery extends QueryInterface { - OrderByQuery(this.field, {this.ascending = true}); + /// {@macro offset_query} + const OrderByQuery(this.field, {this.ascending = true}); + + /// The field of the order by query. final String field; + + /// The ascending of the order by query. final bool ascending; } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart b/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart index f0313c44..95b52190 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart @@ -18,20 +18,43 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +/// {@template crud_repository} +/// An abstract class that represents a SCRUD repository. +/// {@endtemplate} abstract class CrudRepository extends BaseRepository { + /// {@macro crud_repository} + const CrudRepository(); + + /// Creates a new object. FutureOrResult create(Model object, {String? id}); + + /// Gets an object by its [id]. FutureOrResult get(String id); + + /// Gets all objects. FutureOrResult> getAll(); + + /// Updates an object by its [id]. FutureOrResult update( String id, { Model? object, Map? raw, }); + + /// Updates all objects. FutureOrResult updateAll(Map raw); + + /// Deletes an object by its [id]. FutureOrResult delete(String id); + + /// Deletes all objects. FutureOrResult deleteAll(); + + /// Queries objects by [conditions]. FutureOrResult> query(List conditions); + + /// Streams objects by [conditions]. StreamResult> stream({ String? id, List? conditions, diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart index 8a6940b5..ff88a046 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -18,13 +17,19 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; -class Create extends AsyncUseCase { - final CrudRepository _crudRepository; +/// {@template create} +/// A use case that creates an object model. +/// {@endtemplate} +class Create extends AsyncUseCase + with CreateOperation { + /// {@macro create} + const Create(this._crudRepository); - Create(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(Model? params) { diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart index cdebd878..d8ffb17d 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart @@ -17,17 +17,24 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; -class Delete extends AsyncUseCase { - Delete(this._crudRepository); +/// {@template delete} +/// A use case that deletes an object model. +/// {@endtemplate} +class Delete extends AsyncUseCase + with DeleteOperation { + /// {@macro delete} + const Delete(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(String? params) { if (params == null) { - throw ClientException('Id cannot be null.'); + throw const ClientException('Id cannot be null.'); } } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart index a1a36275..ae1935d7 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart @@ -15,11 +15,18 @@ // along with this program. If not, see . import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; -class DeleteAll extends AsyncUseCase { - DeleteAll(this._crudRepository); +/// {@template delete_all} +/// A use case that deletes all the object models. +/// {@endtemplate} +class DeleteAll extends AsyncUseCase + with DeleteOperation { + /// {@macro delete_all} + const DeleteAll(this._crudRepository); + final CrudRepository _crudRepository; @override diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart index 40d6719c..08850936 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart @@ -17,17 +17,24 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; -class Get extends AsyncUseCase { +/// {@template get} +/// A use case that gets an object model. +/// {@endtemplate} +class Get extends AsyncUseCase + with ReadOperation { + /// {@macro get} Get(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(String? params) { if (params == null) { - throw ClientException('Id cannot be null.'); + throw const ClientException('Id cannot be null.'); } } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart index 6fde76b7..63379212 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart @@ -15,12 +15,18 @@ // along with this program. If not, see . import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; -class GetAll - extends AsyncUseCase> { - GetAll(this._crudRepository); +/// {@template get_all} +/// A use case that gets all the object models. +/// {@endtemplate} +class GetAll extends AsyncUseCase> + with ReadOperation> { + /// {@macro get_all} + const GetAll(this._crudRepository); + final CrudRepository _crudRepository; @override diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart index ed7768d4..0b2d178b 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -17,12 +16,19 @@ import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +/// {@template stream_parameters} +/// Represents the parameters for a query stream +/// {@endtemplate} class StreamParameters { - final String? id; - final List? conditions; - - StreamParameters({ + /// {@macro stream_parameters} + const StreamParameters({ this.id, this.conditions, }); + + /// The id of the object model. + final String? id; + + /// The conditions of the query. + final List? conditions; } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart index cbe4cd2b..c44ab784 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -15,14 +14,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template update_parameters} +/// Represents the parameters for an update use case +/// {@endtemplate} class UpdateParameters { - final String id; - final Model? object; - final Map? raw; - - UpdateParameters({ + /// {@macro update_parameters} + const UpdateParameters({ required this.id, this.object, this.raw, }); + + /// The id of the object model. + final String id; + + /// The object model. + final Model? object; + + /// The raw data. + final Map? raw; } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart index 2070b015..4869fa0d 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart @@ -17,19 +17,26 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; +/// {@template query} +/// A use case that queries the object models. +/// {@endtemplate} class Query - extends AsyncUseCase, List> { - Query(this._crudRepository); + extends AsyncUseCase, List> + with ReadOperation, List> { + /// {@macro query} + const Query(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(List? params) { if (params == null) { - throw ClientException('List of conditions cannot be null.'); + throw const ClientException('List of conditions cannot be null.'); } } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream_query.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream_query.dart deleted file mode 100644 index 35e42b9e..00000000 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream_query.dart +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// class Stream extends UseCase> { -// final CrudRepository _crudRepository; - -// Stream(this._crudRepository); - -// @override -// StreamResult> call(StreamParameters params) => -// _crudRepository.stream(id: params.id, conditions: params.conditions); -// } - -// class StreamQuery -// extends StreamUseCase> { -// final CrudRepository _crudRepository; - -// StreamQuery(this._crudRepository); - -// @override -// FutureOr onStart(StreamParameters? params) { -// if(params == null){ -// throw ClientException('Stream parameters cannot be null.'); -// } -// } - -// @override -// FutureOrResult>> call(StreamParameters? params) => -// _crudRepository.stream(); -// } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart index 70c82b73..237e3e9d 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart @@ -17,19 +17,26 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart'; +/// {@template update} +/// A use case that updates an object model. +/// {@endtemplate} class Update - extends AsyncUseCase, void> { - Update(this._crudRepository); + extends AsyncUseCase, void> + with UpdateOperation> { + /// {@macro update} + const Update(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(UpdateParameters? params) { if (params == null) { - throw ClientException('Update parameters cannot be null.'); + throw const ClientException('Update parameters cannot be null.'); } } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart index 60a81957..22c32181 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart @@ -17,18 +17,25 @@ import 'dart:async'; import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart'; +/// {@template update_all} +/// A use case that updates all the object models. +/// {@endtemplate} class UpdateAll - extends AsyncUseCase, void> { - UpdateAll(this._crudRepository); + extends AsyncUseCase, void> + with UpdateOperation> { + /// {@macro update_all} + const UpdateAll(this._crudRepository); + final CrudRepository _crudRepository; @override FutureOr onStart(Map? params) { if (params == null) { - throw ClientException('Data cannot be null.'); + throw const ClientException('Data cannot be null.'); } } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart index b53d1702..4a8d8467 100644 --- a/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart @@ -21,6 +21,5 @@ export 'get.dart'; export 'get_all.dart'; export 'params/params.dart'; export 'query.dart'; -export 'stream_query.dart'; export 'update.dart'; export 'update_all.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_advanced_cubit.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_advanced_cubit.dart new file mode 100644 index 00000000..d41e35d9 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_advanced_cubit.dart @@ -0,0 +1,305 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart'; +import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; +import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/create.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/delete.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/delete_all.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/get.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/get_all.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/query.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/update.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/update_all.dart'; +import 'package:wyatt_crud_bloc/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart'; + +/// {@template crud_cubit_advanced} +/// Cubit that handles CRUD operations with more granularity. +/// {@endtemplate} +abstract class CrudAdvancedCubit + extends CrudBaseCubit { + /// {@macro crud_cubit} + CrudAdvancedCubit() : super(); + + Create? get crudCreate; + DeleteAll? get crudDeleteAll; + Delete? get crudDelete; + GetAll? get crudGetAll; + Get? get crudGet; + Query? get crudQuery; + UpdateAll? get crudUpdateAll; + Update? get crudUpdate; + + FutureOr create(Model model) async { + final crud = crudCreate; + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(model); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + if (stateCopy.data == null) { + return CrudLoaded(model); + } + if (stateCopy.data!.id == model.id) { + return CrudLoaded(model); + } + + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + if (stateCopy.data.isEmpty) { + return CrudListLoaded([model]); + } + final List lst = stateCopy.data.toList()..add(model); + + return CrudListLoaded(lst); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr delete(String id) async { + final crud = crudDelete; + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(id); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + if (stateCopy.data?.id == id) { + return CrudLoaded(null); + } + + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded( + stateCopy.data.where((element) => element?.id != id).toList(), + ); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr deleteAll() async { + final crud = crudDeleteAll; + if (crud == null) { + return; + } + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(null); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + return CrudLoaded(null); + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded(const []); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr get(String id) async { + final crud = crudGet; + if (crud == null) { + return; + } + emit(const CrudLoading()); + final result = await crud.call(id); + emit( + result.fold( + CrudLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr getAll() async { + final crud = crudGetAll; + if (crud == null) { + return; + } + emit(const CrudLoading()); + final result = await crud.call(null); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr query(List conditions) async { + final crud = crudQuery; + if (crud == null) { + return; + } + + emit(const CrudLoading()); + final result = await crud.call(conditions); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr update(UpdateParameters param) async { + final crud = crudUpdate; + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(param); + emit( + await result.foldAsync( + (_) async { + if (stateCopy is CrudLoaded) { + if (stateCopy.data?.id == param.id) { + // Same object, need to update actual stateCopy + final crudGet = this.crudGet; + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final newVersion = await crudGet.call(param.id); + if (newVersion.isOk) { + return CrudLoaded(newVersion.ok); + } + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + final bool listContains = + stateCopy.data.any((element) => element?.id == param.id); + if (listContains) { + // Loaded objects contains the modified object. + + final crudGet = this.crudGet; + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final newVersion = await crudGet.call(param.id); + if (newVersion.isOk) { + final newList = stateCopy.data + .where( + (element) => element?.id != param.id, + ) + .toList(); + return CrudListLoaded(newList + [newVersion.ok]); + } + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } + + FutureOr updateAll(Map param) async { + final crud = crudUpdateAll; + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(param); + emit( + await result.foldAsync( + (_) async { + if (stateCopy is CrudLoaded) { + // Same object, need to update actual stateCopy + final crudGet = this.crudGet; + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final actualId = stateCopy.data?.id; + final newVersion = await crudGet.call(actualId ?? ''); + if (newVersion.isOk) { + return CrudLoaded(newVersion.ok); + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + final crudQuery = this.crudQuery; + if (crudQuery == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + // Load all id to retrieve exactly same object + // (not all because previous stateCopy can be a query result) + final List ids = stateCopy.data + .map( + (e) => e?.id, + ) + .toList(); + final result = await crudQuery.call([ + WhereQuery( + WhereQueryType.whereIn, + 'id', + ids, + ) + ]); + if (result.isOk) { + return CrudListLoaded(result.ok ?? []); + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } +} diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart new file mode 100644 index 00000000..c694b880 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart @@ -0,0 +1,28 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'crud_state.dart'; + +/// {@template crud_base_cubit} +/// A base [Cubit] that handles SCRUD operations. +/// {@endtemplate} +abstract class CrudBaseCubit extends Cubit { + /// {@macro crud_base_cubit} + CrudBaseCubit() : super(const CrudInitial()); +} diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_state.dart similarity index 58% rename from packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart rename to packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_state.dart index f8ab26e2..64f2479a 100644 --- a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_base_cubit/crud_state.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'crud_cubit.dart'; +part of 'crud_base_cubit.dart'; abstract class CrudState extends Equatable { const CrudState(); @@ -23,18 +23,17 @@ abstract class CrudState extends Equatable { List get props => []; } -class CrudInitial extends CrudState {} - -class CrudLoading extends CrudState {} - -abstract class CrudSuccess extends CrudState { - const CrudSuccess(); +/// Initial state of the CrudBaseCubit. +class CrudInitial extends CrudState { + const CrudInitial(); } -class CrudOkReturn extends CrudState { - const CrudOkReturn(); +/// Loading state of the CrudBaseCubit. +class CrudLoading extends CrudState { + const CrudLoading(); } +/// Error state of the CrudBaseCubit. class CrudError extends CrudState { const CrudError(this.message); final String? message; @@ -43,6 +42,24 @@ class CrudError extends CrudState { List get props => [message]; } +/// Success state of the CrudBaseCubit. +/// This state is used to indicate that the operation was successful. +/// Can be one or list of objects. +abstract class CrudSuccess extends CrudState { + const CrudSuccess(); +} + +/// Success state of the CrudBaseCubit. +/// This state is used to indicate that the operation was successful. +/// Contains no objects. +/// Used for create, update, delete operations. +class CrudOkReturn extends CrudSuccess { + const CrudOkReturn(); +} + +/// Loaded state of the CrudBaseCubit. +/// This state is used to indicate that the operation was successful. +/// Contains one object. class CrudLoaded extends CrudSuccess { const CrudLoaded(this.data); final T? data; @@ -51,6 +68,9 @@ class CrudLoaded extends CrudSuccess { List get props => [data]; } +/// Loaded state of the CrudBaseCubit. +/// This state is used to indicate that the operation was successful. +/// Contains list of objects. class CrudListLoaded extends CrudSuccess { const CrudListLoaded(this.data); final List data; diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_cubit.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_cubit.dart new file mode 100644 index 00000000..5d18975f --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/blocs/crud_cubit.dart @@ -0,0 +1,369 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart'; +import 'package:wyatt_crud_bloc/src/core/mixins/operation.dart'; +import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; +import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/create.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/delete.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/delete_all.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/get.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/get_all.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/query.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/update.dart'; +import 'package:wyatt_crud_bloc/src/domain/usecases/update_all.dart'; +import 'package:wyatt_crud_bloc/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart'; + +/// {@template crud_cubit} +/// Cubit that handles CRUD operations. +/// {@endtemplate} +abstract class CrudCubit extends CrudBaseCubit { + /// {@macro crud_cubit} + CrudCubit() : super(); + + /// Create operation. + /// Can be create. + CreateOperation? get createOperation; + + /// Read operation. + /// Can be get, getAll, query. + ReadOperation? get readOperation; + + /// Update operation. + /// Can be update, updateAll. + UpdateOperation? get updateOperation; + + /// Delete operation. + /// Can be delete or deleteAll. + DeleteOperation? get deleteOperation; + + Expected? _checkOperation(dynamic operation) { + if (operation == null) { + return null; + } + if (operation is! Expected) { + return null; + } + return operation; + } + + FutureOr create(Model model) async { + if (_checkOperation>(createOperation) != null) { + return _create(model); + } + } + + FutureOr read({String? id, List? conditions}) async { + if (_checkOperation>(readOperation) != null && id != null) { + return _get(id); + } + if (_checkOperation>(readOperation) != null) { + return _getAll(); + } + if (_checkOperation>(readOperation) != null && + conditions != null) { + return _query(conditions); + } + if (_checkOperation>(readOperation) != null && + conditions == null) { + return _getAll(); + } + } + + FutureOr update( + UpdateParameters? single, + Map? all, + ) async { + if (_checkOperation>(updateOperation) != null && + single != null) { + return _update(single); + } + + if (_checkOperation>(updateOperation) != null && + all != null) { + return _updateAll(all); + } + } + + FutureOr delete({String? id}) async { + if (_checkOperation>(deleteOperation) != null && id != null) { + return _delete(id); + } + if (_checkOperation>(deleteOperation) != null) { + return _deleteAll(); + } + } + + FutureOr _create(Model model) async { + final crud = _checkOperation>(createOperation); + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(model); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + if (stateCopy.data == null) { + return CrudLoaded(model); + } + if (stateCopy.data!.id == model.id) { + return CrudLoaded(model); + } + + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + if (stateCopy.data.isEmpty) { + return CrudListLoaded([model]); + } + final List lst = stateCopy.data.toList()..add(model); + + return CrudListLoaded(lst); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _delete(String id) async { + final crud = _checkOperation>(deleteOperation); + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(id); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + if (stateCopy.data?.id == id) { + return CrudLoaded(null); + } + + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded( + stateCopy.data.where((element) => element?.id != id).toList(), + ); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _deleteAll() async { + final crud = _checkOperation>(deleteOperation); + if (crud == null) { + return; + } + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(null); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + return CrudLoaded(null); + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded(const []); + } + + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _get(String id) async { + final crud = _checkOperation>(readOperation); + if (crud == null) { + return; + } + emit(const CrudLoading()); + final result = await crud.call(id); + emit( + result.fold( + CrudLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _getAll() async { + final crud = _checkOperation>(readOperation); + if (crud == null) { + return; + } + emit(const CrudLoading()); + final result = await crud.call(null); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _query(List conditions) async { + final crud = _checkOperation>(readOperation); + if (crud == null) { + return; + } + + emit(const CrudLoading()); + final result = await crud.call(conditions); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + + FutureOr _update(UpdateParameters param) async { + final crud = _checkOperation>(updateOperation); + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(param); + emit( + await result.foldAsync( + (_) async { + if (stateCopy is CrudLoaded) { + if (stateCopy.data?.id == param.id) { + // Same object, need to update actual stateCopy + final crudGet = _checkOperation>(readOperation); + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final newVersion = await crudGet.call(param.id); + if (newVersion.isOk) { + return CrudLoaded(newVersion.ok); + } + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + final bool listContains = + stateCopy.data.any((element) => element?.id == param.id); + if (listContains) { + // Loaded objects contains the modified object. + + final crudGet = _checkOperation>(readOperation); + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final newVersion = await crudGet.call(param.id); + if (newVersion.isOk) { + final newList = stateCopy.data + .where( + (element) => element?.id != param.id, + ) + .toList(); + return CrudListLoaded(newList + [newVersion.ok]); + } + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } + + FutureOr _updateAll(Map param) async { + final crud = _checkOperation>(updateOperation); + if (crud == null) { + return; + } + + final stateCopy = state; + emit(const CrudLoading()); + final result = await crud.call(param); + emit( + await result.foldAsync( + (_) async { + if (stateCopy is CrudLoaded) { + // Same object, need to update actual stateCopy + final crudGet = _checkOperation>(readOperation); + if (crudGet == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + final actualId = stateCopy.data?.id; + final newVersion = await crudGet.call(actualId ?? ''); + if (newVersion.isOk) { + return CrudLoaded(newVersion.ok); + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + final crudQuery = _checkOperation>(readOperation); + if (crudQuery == null) { + // No read operation, can't update stateCopy. + return stateCopy; + } + // Load all id to retrieve exactly same object + // (not all because previous stateCopy can be a query result) + final List ids = stateCopy.data + .map( + (e) => e?.id, + ) + .toList(); + final result = await crudQuery.call([ + WhereQuery( + WhereQueryType.whereIn, + 'id', + ids, + ) + ]); + if (result.isOk) { + return CrudListLoaded(result.ok ?? []); + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } +} diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart index 62f1faaa..d864ce7a 100644 --- a/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart @@ -15,15 +15,19 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:wyatt_crud_bloc/src/features/crud/cubit/crud_cubit.dart'; +import 'package:wyatt_crud_bloc/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart'; +/// {@template crud_builder} +/// A widget that builds itself based on the latest snapshot of interaction +/// with a [CrudBaseCubit]. +/// +/// * I = Initial State +/// * L = Loading State +/// * S = Success State +/// * E = Error State +/// {@endtemplate} class CrudBuilder extends StatelessWidget { - /// `` - /// - /// - I: the Initial State - /// - L: the Loading State - /// - S: the Success State - /// - E: the Error State + /// {@macro crud_builder} const CrudBuilder({ required this.state, required this.builder, @@ -34,11 +38,11 @@ class CrudBuilder extends StatelessWidget { super.key, }); - /// `` + /// {@macro crud_builder} /// - /// - S: the Success State - /// - /// For CrudStates only. + /// This factory constructor is used to create a [CrudBuilder] with + /// [CrudState]s. `S` is the Success State, and it must be a subtype of + /// [CrudSuccess]. It the only type that you have to specify. static CrudBuilder typed({ required CrudState state, diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart index cb18407c..16113197 100644 --- a/packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart @@ -14,5 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +export 'blocs/crud_advanced_cubit.dart'; +export 'blocs/crud_base_cubit/crud_base_cubit.dart'; +export 'blocs/crud_cubit.dart'; export 'builder/builder.dart'; -export 'cubit/crud_cubit.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart deleted file mode 100644 index dcb466aa..00000000 --- a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; - -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_architecture/wyatt_architecture.dart'; -import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart'; -import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart'; -import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/create.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/delete.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/delete_all.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/get.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/get_all.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/query.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/update.dart'; -import 'package:wyatt_crud_bloc/src/domain/usecases/update_all.dart'; - -part 'crud_state.dart'; - -abstract class CrudCubit extends Cubit { - CrudCubit() : super(CrudInitial()); - Create? get crudCreate; - DeleteAll? get crudDeleteAll; - Delete? get crudDelete; - GetAll? get crudGetAll; - Get? get crudGet; - Query? get crudQuery; - UpdateAll? get crudUpdateAll; - Update? get crudUpdate; - - FutureOr create(Model model) async { - if (crudCreate != null) { - final stateCopy = state; - emit(CrudLoading()); - final result = await crudCreate!.call(model); - emit( - result.fold( - (_) { - if (stateCopy is CrudLoaded) { - return stateCopy; - } - if (stateCopy is CrudListLoaded) { - if (stateCopy.data.isEmpty) { - return CrudListLoaded([model]); - } - final List lst = stateCopy.data.toList()..add(model); - return CrudListLoaded(lst); - } - return const CrudOkReturn(); - }, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr delete(String id) async { - if (crudDelete != null) { - final stateCopy = state; - emit(CrudLoading()); - final result = await crudDelete!.call(id); - emit( - result.fold( - (_) { - if (stateCopy is CrudLoaded) { - return stateCopy; - } - if (stateCopy is CrudListLoaded) { - return CrudListLoaded( - stateCopy.data.where((element) => element?.id != id).toList(), - ); - } - return const CrudOkReturn(); - }, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr deleteAll() async { - if (crudDeleteAll != null) { - final stateCopy = state; - emit(CrudLoading()); - final result = await crudDeleteAll!.call(null); - emit( - result.fold( - (_) { - if (stateCopy is CrudLoaded) { - return CrudLoaded(null); - } - if (stateCopy is CrudListLoaded) { - return CrudListLoaded(const []); - } - return const CrudOkReturn(); - }, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr get(String id) async { - if (crudGet != null) { - emit(CrudLoading()); - final result = await crudGet!.call(id); - emit( - result.fold( - CrudLoaded.new, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr getAll() async { - if (crudGetAll != null) { - emit(CrudLoading()); - final result = await crudGetAll!.call(null); - emit( - result.fold( - CrudListLoaded.new, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr query(List conditions) async { - if (crudQuery != null) { - emit(CrudLoading()); - final result = await crudQuery!.call(conditions); - emit( - result.fold( - CrudListLoaded.new, - (error) => CrudError(error.toString()), - ), - ); - } - } - - FutureOr update(UpdateParameters param) async { - if (crudUpdate != null) { - final stateCopy = state; - emit(CrudLoading()); - final result = await crudUpdate!.call(param); - emit( - await result.foldAsync( - (_) async { - if (stateCopy is CrudLoaded) { - if (stateCopy.data?.id == param.id) { - // Same object, need to update actual stateCopy - if (crudGet == null) { - throw ClientException( - 'Need to init Get usecase to use update.', - ); - } - final newVersion = await crudGet!.call(param.id); - if (newVersion.isOk) { - return CrudLoaded(newVersion.ok); - } - } - return stateCopy; - } - if (stateCopy is CrudListLoaded) { - final bool listContains = - stateCopy.data.any((element) => element?.id == param.id); - if (listContains) { - // Loaded objects contains the modified object. - if (crudGet == null) { - throw ClientException( - 'Need to init Get usecase to use update.', - ); - } - final newVersion = await crudGet!.call(param.id); - if (newVersion.isOk) { - final newList = stateCopy.data - .where( - (element) => element?.id != param.id, - ) - .toList(); - return CrudListLoaded(newList + [newVersion.ok]); - } - } - return stateCopy; - } - return const CrudOkReturn(); - }, - (error) async => CrudError(error.toString()), - ), - ); - } - } - - FutureOr updateAll(Map param) async { - if (crudUpdateAll != null) { - final stateCopy = state; - emit(CrudLoading()); - final result = await crudUpdateAll!.call(param); - emit( - await result.foldAsync( - (_) async { - if (stateCopy is CrudLoaded) { - // Same object, need to update actual stateCopy - if (crudGet == null) { - throw ClientException( - 'Need to init Get usecase to use updateAll.', - ); - } - final actualId = stateCopy.data?.id; - final newVersion = await crudGet!.call(actualId ?? ''); - if (newVersion.isOk) { - return CrudLoaded(newVersion.ok); - } - return stateCopy; - } - if (stateCopy is CrudListLoaded) { - if (crudQuery == null) { - throw ClientException( - 'Need to init Query usecase to use updateAll.', - ); - } - // Load all id to retrieve exactly same object - // (not all because previous stateCopy can be a query result) - final List ids = stateCopy.data - .map( - (e) => e?.id, - ) - .toList(); - final result = await crudQuery!.call([ - WhereQuery( - WhereQueryType.whereIn, - 'id', - ids, - ) - ]); - if (result.isOk) { - return CrudListLoaded(result.ok ?? []); - } - return stateCopy; - } - return const CrudOkReturn(); - }, - (error) async => CrudError(error.toString()), - ), - ); - } - } -} diff --git a/packages/wyatt_crud_bloc/pubspec.yaml b/packages/wyatt_crud_bloc/pubspec.yaml index 058de9d4..09b9d2b2 100644 --- a/packages/wyatt_crud_bloc/pubspec.yaml +++ b/packages/wyatt_crud_bloc/pubspec.yaml @@ -10,8 +10,7 @@ environment: flutter: ">=1.17.0" dependencies: - flutter: - sdk: flutter + flutter: { sdk: flutter } flutter_bloc: ^8.1.1 equatable: ^2.0.5 @@ -26,9 +25,8 @@ dependencies: version: ^0.0.4 dev_dependencies: - flutter_test: - sdk: flutter + flutter_test: { sdk: flutter } bloc_test: ^9.1.0 wyatt_analysis: - hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ - version: 2.4.1 + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.4.1 diff --git a/packages/wyatt_deferred_widget_annotation/.gitignore b/packages/wyatt_deferred_widget_annotation/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_deferred_widget_annotation/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_annotation/.pubignore b/packages/wyatt_deferred_widget_annotation/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_deferred_widget_annotation/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_annotation/AUTHORS b/packages/wyatt_deferred_widget_annotation/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_deferred_widget_annotation/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_annotation/LICENSE b/packages/wyatt_deferred_widget_annotation/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_deferred_widget_annotation/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_gen/.gitignore b/packages/wyatt_deferred_widget_gen/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_deferred_widget_gen/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_gen/.pubignore b/packages/wyatt_deferred_widget_gen/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_deferred_widget_gen/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_gen/AUTHORS b/packages/wyatt_deferred_widget_gen/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_deferred_widget_gen/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_deferred_widget_gen/LICENSE b/packages/wyatt_deferred_widget_gen/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_deferred_widget_gen/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_form_bloc/.gitignore b/packages/wyatt_form_bloc/.gitignore deleted file mode 100644 index 65c34dc8..00000000 --- a/packages/wyatt_form_bloc/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_form_bloc/.gitignore b/packages/wyatt_form_bloc/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_form_bloc/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_form_bloc/.pubignore b/packages/wyatt_form_bloc/.pubignore deleted file mode 100644 index 11610c5a..00000000 --- a/packages/wyatt_form_bloc/.pubignore +++ /dev/null @@ -1,2 +0,0 @@ -firebase_options.dart -.vscode \ No newline at end of file diff --git a/packages/wyatt_form_bloc/.pubignore b/packages/wyatt_form_bloc/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_form_bloc/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_form_bloc/AUTHORS b/packages/wyatt_form_bloc/AUTHORS deleted file mode 100644 index b6d7d765..00000000 --- a/packages/wyatt_form_bloc/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_form_bloc/AUTHORS b/packages/wyatt_form_bloc/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_form_bloc/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_form_bloc/LICENSE b/packages/wyatt_form_bloc/LICENSE deleted file mode 100644 index 3b2646b3..00000000 --- a/packages/wyatt_form_bloc/LICENSE +++ /dev/null @@ -1,692 +0,0 @@ - - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_form_bloc/LICENSE b/packages/wyatt_form_bloc/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_form_bloc/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_http_client/.gitignore b/packages/wyatt_http_client/.gitignore deleted file mode 100644 index 65c34dc8..00000000 --- a/packages/wyatt_http_client/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_http_client/.gitignore b/packages/wyatt_http_client/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_http_client/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_http_client/.pubignore b/packages/wyatt_http_client/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_http_client/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_http_client/AUTHORS b/packages/wyatt_http_client/AUTHORS deleted file mode 100644 index b6d7d765..00000000 --- a/packages/wyatt_http_client/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_http_client/AUTHORS b/packages/wyatt_http_client/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_http_client/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_http_client/LICENSE b/packages/wyatt_http_client/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_http_client/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_http_client/LICENSE b/packages/wyatt_http_client/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_http_client/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_http_client/README.md b/packages/wyatt_http_client/README.md index ee2b78d5..aee439ed 100644 --- a/packages/wyatt_http_client/README.md +++ b/packages/wyatt_http_client/README.md @@ -16,12 +16,10 @@ * along with this program. If not, see . --> -# Dart - HTTP Client +# HTTP Client

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Dart & Flutter

@@ -52,13 +50,13 @@ For example, if you want to log every request, and simplify an url you can use p ```dart // Create the Pipeline final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( + ..addMiddleware( + const UriPrefixMiddleware( protocol: Protocols.http, authority: 'localhost:80', ), ) - .addMiddleware(SimpleLoggerMiddleware()); + ..addMiddleware(const SimpleLoggerMiddleware()); ``` Then if you print the pipeline, @@ -94,20 +92,20 @@ Let's start by creating the Pipeline: ```dart final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( + ..addMiddleware( + const UriPrefixMiddleware( protocol: Protocols.http, authority: 'localhost:80', ), ) - .addMiddleware(BodyToJsonMiddleware()) - .addMiddleware( - UnsafeAuthMiddleware( + ..addMiddleware(const BodyToJsonMiddleware()) + ..addMiddleware( + const UnsafeAuthMiddleware( username: 'wyatt', password: 'motdepasse', ), ) - .addMiddleware(SimpleLoggerMiddleware()); + ..addMiddleware(SimpleLoggerMiddleware()); ``` Then simply create a client and make a call. @@ -128,14 +126,14 @@ So now we want a real authentication. ```dart final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( + ..addMiddleware( + const UriPrefixMiddleware( protocol: Protocols.http, authority: 'localhost:80', ), ) - .addMiddleware(BodyToJsonMiddleware()) - .addMiddleware( + ..addMiddleware(const BodyToJsonMiddleware()) + ..addMiddleware( RefreshTokenAuthMiddleware( authorizationEndpoint: '/auth/sign-in', tokenEndpoint: '/auth/refresh', @@ -144,7 +142,7 @@ final Pipeline pipeline = Pipeline() unauthorized: HttpStatus.forbidden, ), ) - .addMiddleware(SimpleLoggerMiddleware()); + ..addMiddleware(const SimpleLoggerMiddleware()); ``` > Here we just change `UnsafeAuthMiddleware` by `RefreshTokenAuthMiddleware` and the whole app while adapt to a new authentication system. @@ -157,6 +155,8 @@ You can create your own middleware by implementing `Middleware` class, and use m class SimpleLoggerMiddleware with OnRequestMiddleware, OnResponseMiddleware implements Middleware { + + const SimpleLoggerMiddleware(); @override String getName() => 'SimpleLogger'; diff --git a/packages/wyatt_http_client/example/example.dart b/packages/wyatt_http_client/example/example.dart new file mode 100644 index 00000000..a5c529ea --- /dev/null +++ b/packages/wyatt_http_client/example/example.dart @@ -0,0 +1,78 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_http_client/wyatt_http_client.dart'; + +Future testSimpleGet() async { + print('testSimpleGet'); + final pipeline = Pipeline() + ..addMiddleware(const BodyToJsonMiddleware()) + ..addMiddleware(const SimpleLoggerMiddleware()); + + final client = MiddlewareClient(pipeline: pipeline); + + final response = await client + .get(Uri.parse('https://jsonplaceholder.typicode.com/todos/1')); + print(response.body); +} + +Future testUriPrefix() async { + print('testUriPrefix'); + final pipeline = Pipeline() + ..addMiddleware( + const UriPrefixMiddleware( + protocol: Protocols.https, + authority: 'jsonplaceholder.typicode.com', + ), + ) + ..addMiddleware(const BodyToJsonMiddleware()) + ..addMiddleware(const SimpleLoggerMiddleware()); + + final client = MiddlewareClient(pipeline: pipeline); + + final response = await client.get(Uri.parse('/todos/1')); + print(response.body); +} + +Future testBasicAuth() async { + print('testBasicAuth'); + final pipeline = Pipeline() + ..addMiddleware( + const BasicAuthMiddleware( + username: 'guest', + password: 'guest', + ), + ) + ..addMiddleware(const BodyToJsonMiddleware()) + ..addMiddleware(const SimpleLoggerMiddleware()); + + final client = MiddlewareClient(pipeline: pipeline); + + final response = + await client.get(Uri.parse('https://jigsaw.w3.org/HTTP/Basic/')); + + if (HttpStatus.from(response.statusCode).isSuccess()) { + print("🎉 You're in!"); + } else { + print("⭕️ Nope, you're not in."); + } +} + +void main(List args) { + testSimpleGet(); + testUriPrefix(); + testBasicAuth(); +} diff --git a/packages/wyatt_http_client/example/http_client_example.dart b/packages/wyatt_http_client/example/http_client_example.dart deleted file mode 100644 index 43009540..00000000 --- a/packages/wyatt_http_client/example/http_client_example.dart +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; -import 'dart:io'; - -import 'package:wyatt_http_client/wyatt_http_client.dart'; - -String lastToken = ''; -int token = 0; - -void printAuth(HttpRequest req) { - print( - 'Authorization => ' - "${req.headers.value('Authorization') ?? 'no authorization header'}", - ); -} - -Future handleBasic(HttpRequest req) async { - printAuth(req); -} - -Future handleBasicNegotiate(HttpRequest req) async { - if (req.headers.value('Authorization') == null) { - req.response.statusCode = HttpStatus.unauthorized.statusCode; - req.response.headers.set(HeaderKeys.wwwAuthenticate, 'Basic realm="Wyatt"'); - print(req.response.headers.value('WWW-Authenticate')); - return req.response.close(); - } - printAuth(req); -} - -Future handleBearer(HttpRequest req) async { - printAuth(req); -} - -Future handleDigest(HttpRequest req) async { - if (req.headers.value('Authorization') == null) { - req.response.statusCode = HttpStatus.unauthorized.statusCode; - req.response.headers.set( - 'WWW-Authenticate', - 'Digest realm="Wyatt", ' - 'qop="auth,auth-int", ' - 'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' - 'opaque="5ccc069c403ebaf9f0171e9517f40e41"', - ); - print(req.response.headers.value('WWW-Authenticate')); - return req.response.close(); - } - printAuth(req); -} - -Future handleUnsafe(HttpRequest req) async { - print( - 'Query parameters => ' - '${req.uri.queryParameters}', - ); -} - -Future handleOauth2RefreshToken(HttpRequest req) async { - final action = req.uri.queryParameters['action']; - if (action == null) { - printAuth(req); - } - - switch (action) { - case 'login': - if (req.method == 'POST') { - token++; - req.response.write( - '{"accessToken": "access-token-awesome$token", ' - '"refreshToken": "refresh-token-awesome$token"}', - ); - } - break; - case 'refresh': - printAuth(req); - if (req.method == 'GET') { - token++; - req.response.write('{"accessToken": "access-token-refreshed$token"}'); - } - break; - case 'access-denied': - final String receivedToken = req.headers.value('Authorization') ?? ''; - if (receivedToken != '' && - lastToken != '' && - receivedToken != lastToken) { - lastToken = receivedToken; - printAuth(req); - return req.response.close(); - } else { - lastToken = receivedToken; - req.response.statusCode = HttpStatus.unauthorized.statusCode; - return req.response.close(); - } - default: - break; - } -} - -Future server() async { - final server = await HttpServer.bind(InternetAddress.anyIPv6, 8080); - var error = 0; - var token = 0; - await server.forEach((request) { - print('[${request.method}] ${request.uri}'); - switch (request.uri.path) { - case '/test/basic-test': - handleBasic(request); - break; - case '/test/basic-test-with-negotiate': - handleBasicNegotiate(request); - break; - case '/test/digest-test': - handleDigest(request); - break; - case '/test/apikey-test': - handleBearer(request); - break; - case '/test/bearer-test': - handleBearer(request); - break; - case '/test/unsafe-test': - handleUnsafe(request); - break; - case '/test/oauth2-test': - handleOauth2RefreshToken(request); - break; - - case '/test/bearer-login': - if (request.method == 'POST') { - request.response.write('{"token": "access-token-test"}'); - } - break; - - case '/test/oauth2-test-error': - error++; - print('Error $error'); - if (error >= 3) { - print('Authorized'); - error = 0; - } else { - request.response.statusCode = HttpStatus.unauthorized.statusCode; - } - break; - case '/test/oauth2-test-timeout': - error++; - print('Error $error'); - request.response.statusCode = HttpStatus.unauthorized.statusCode; - break; - case '/test/oauth2-login': - if (request.method == 'POST') { - token++; - request.response.write( - '{"accessToken": "access-token-awesome$token", ' - '"refreshToken": "refresh-token-awesome$token"}', - ); - } - break; - case '/test/oauth2-refresh': - print( - 'Authorization => ' - "${request.headers.value('Authorization') ?? 'no refresh token'}", - ); - if (request.method == 'GET') { - token++; - request.response - .write('{"accessToken": "access-token-refreshed$token"}'); - } - break; - case '/test/oauth2-refresh-error': - request.response.statusCode = HttpStatus.unauthorized.statusCode; - break; - - default: - print(' => Unknown path or method'); - request.response.statusCode = HttpStatus.notFound.statusCode; - } - request.response.close(); - print('===================='); - }); -} - -Future main() async { - unawaited(server()); - const base = 'localhost:8080'; - final uriPrefix = UriPrefixMiddleware( - protocol: Protocols.http, - authority: base, - ); - final jsonEncoder = BodyToJsonMiddleware(); - final logger = SimpleLoggerMiddleware(); - - // Basic - final basicAuth = BasicAuthMiddleware( - username: 'username', - password: 'password', - ); - final basic = MiddlewareClient( - pipeline: Pipeline.fromIterable([ - uriPrefix, - basicAuth, - logger, - ]), - ); - await basic.get(Uri.parse('/test/basic-test')); - - // Digest - final digestAuth = DigestAuthMiddleware( - username: 'Mufasa', - password: 'Circle Of Life', - ); - final digest = MiddlewareClient( - pipeline: Pipeline.fromIterable([ - uriPrefix, - digestAuth, - logger, - ]), - ); - await digest.get(Uri.parse('/test/digest-test')); - - // // Bearer - // final bearer = BearerAuthenticationClient( - // token: 'access-token-test', - // inner: restClient, - // ); - // await bearer.get(Uri.parse('/test/bearer-test')); - - // // API Key - // final apiKey = BearerAuthenticationClient( - // token: 'awesome-api-key', - // authenticationMethod: 'ApiKey', - // inner: restClient, - // ); - // await apiKey.get(Uri.parse('/test/apikey-test')); - - // Unsafe URL - final unsafeAuth = UnsafeAuthMiddleware( - username: 'Mufasa', - password: 'Circle Of Life', - ); - final unsafe = MiddlewareClient( - pipeline: Pipeline.fromIterable([ - uriPrefix, - unsafeAuth, - logger, - ]), - ); - await unsafe.get(Uri.parse('/test/unsafe-test')); - - // OAuth2 - final refreshTokenAuth = RefreshTokenAuthMiddleware( - authorizationEndpoint: '/test/oauth2-test?action=login', - tokenEndpoint: '/test/oauth2-test?action=refresh', - accessTokenParser: (body) => body['accessToken']! as String, - refreshTokenParser: (body) => body['refreshToken']! as String, - ); - final refreshToken = MiddlewareClient( - pipeline: Pipeline.fromIterable([ - uriPrefix, - jsonEncoder, - refreshTokenAuth, - logger, - ]), - ); - await refreshToken.get(Uri.parse('/test/oauth2-test')); - // Login - await refreshToken.post( - Uri.parse('/test/oauth2-test'), - body: { - 'username': 'username', - 'password': 'password', - }, - ); - await refreshToken.get(Uri.parse('/test/oauth2-test')); - // await refreshToken.refresh(); - // await refreshToken.get(Uri.parse('/test/oauth2-test')); - // await refreshToken.get(Uri.parse('/test/oauth2-test?action=access-denied')); - - exit(0); -} diff --git a/packages/wyatt_http_client/example/http_client_fastapi_example.dart b/packages/wyatt_http_client/example/http_client_fastapi_example.dart deleted file mode 100644 index b9a900fd..00000000 --- a/packages/wyatt_http_client/example/http_client_fastapi_example.dart +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// ignore_for_file: public_member_api_docs, sort_constructors_first -import 'dart:convert'; - -import 'package:wyatt_http_client/src/middleware_client.dart'; -import 'package:wyatt_http_client/src/middlewares/body_to_json_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/refresh_token_auth_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/simple_logger_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/uri_prefix_middleware.dart'; -import 'package:wyatt_http_client/src/pipeline.dart'; -import 'package:wyatt_http_client/src/utils/http_status.dart'; -import 'package:wyatt_http_client/src/utils/protocols.dart'; - -enum EmailVerificationAction { - signUp, - resetPassword, - changeEmail; - - String toSnakeCase() => name.splitMapJoin( - RegExp('[A-Z]'), - onMatch: (m) => '_${m[0]?.toLowerCase()}', - onNonMatch: (n) => n, - ); - - factory EmailVerificationAction.fromString(String str) => - EmailVerificationAction.values.firstWhere( - (element) => element.toSnakeCase() == str, - ); -} - -class VerifyCode { - final String email; - final String verificationCode; - final EmailVerificationAction action; - VerifyCode({ - required this.email, - required this.verificationCode, - required this.action, - }); - - VerifyCode copyWith({ - String? email, - String? verificationCode, - EmailVerificationAction? action, - }) => - VerifyCode( - email: email ?? this.email, - verificationCode: verificationCode ?? this.verificationCode, - action: action ?? this.action, - ); - - Map toMap() => { - 'email': email, - 'verification_code': verificationCode, - 'action': action.toSnakeCase(), - }; - - factory VerifyCode.fromMap(Map map) => VerifyCode( - email: map['email'] as String, - verificationCode: map['verification_code'] as String, - action: EmailVerificationAction.fromString(map['action'] as String), - ); - - String toJson() => json.encode(toMap()); - - factory VerifyCode.fromJson(String source) => - VerifyCode.fromMap(json.decode(source) as Map); - - @override - String toString() => 'VerifyCode(email: $email, verificationCode: ' - '$verificationCode, action: $action)'; -} - -class Account { - final String email; - final String? sessionId; - Account({ - required this.email, - this.sessionId, - }); - - Account copyWith({ - String? email, - String? sessionId, - }) => - Account( - email: email ?? this.email, - sessionId: sessionId ?? this.sessionId, - ); - - Map toMap() => { - 'email': email, - 'session_id': sessionId, - }; - - factory Account.fromMap(Map map) => Account( - email: map['email'] as String, - sessionId: - map['session_id'] != null ? map['session_id'] as String : null, - ); - - String toJson() => json.encode(toMap()); - - factory Account.fromJson(String source) => - Account.fromMap(json.decode(source) as Map); - - @override - String toString() => 'Account(email: $email, sessionId: $sessionId)'; -} - -class SignUp { - final String sessionId; - final String password; - SignUp({ - required this.sessionId, - required this.password, - }); - - SignUp copyWith({ - String? sessionId, - String? password, - }) => - SignUp( - sessionId: sessionId ?? this.sessionId, - password: password ?? this.password, - ); - - Map toMap() => { - 'session_id': sessionId, - 'password': password, - }; - - factory SignUp.fromMap(Map map) => SignUp( - sessionId: map['session_id'] as String, - password: map['password'] as String, - ); - - String toJson() => json.encode(toMap()); - - factory SignUp.fromJson(String source) => - SignUp.fromMap(json.decode(source) as Map); - - @override - String toString() => 'SignUp(sessionId: $sessionId, password: $password)'; -} - -class TokenSuccess { - final String accessToken; - final String refreshToken; - final Account account; - TokenSuccess({ - required this.accessToken, - required this.refreshToken, - required this.account, - }); - - TokenSuccess copyWith({ - String? accessToken, - String? refreshToken, - Account? account, - }) => - TokenSuccess( - accessToken: accessToken ?? this.accessToken, - refreshToken: refreshToken ?? this.refreshToken, - account: account ?? this.account, - ); - - Map toMap() => { - 'access_token': accessToken, - 'refresh_token': refreshToken, - 'account': account.toMap(), - }; - - factory TokenSuccess.fromMap(Map map) => TokenSuccess( - accessToken: map['access_token'] as String, - refreshToken: map['refresh_token'] as String, - account: Account.fromMap(map['account'] as Map), - ); - - String toJson() => json.encode(toMap()); - - factory TokenSuccess.fromJson(String source) => - TokenSuccess.fromMap(json.decode(source) as Map); - - @override - String toString() => 'TokenSuccess(accessToken: $accessToken, refreshToken: ' - '$refreshToken, account: $account)'; -} - -class Login { - final String email; - final String password; - Login({ - required this.email, - required this.password, - }); - - Login copyWith({ - String? email, - String? password, - }) => - Login( - email: email ?? this.email, - password: password ?? this.password, - ); - - Map toMap() => { - 'email': email, - 'password': password, - }; - - factory Login.fromMap(Map map) => Login( - email: map['email'] as String, - password: map['password'] as String, - ); - - String toJson() => json.encode(toMap()); - - factory Login.fromJson(String source) => - Login.fromMap(json.decode(source) as Map); - - @override - String toString() => 'Login(email: $email, password: $password)'; -} - -class FastAPI { - final String baseUrl; - final MiddlewareClient client; - final int apiVersion; - - FastAPI({ - this.baseUrl = 'localhost:80', - MiddlewareClient? client, - this.apiVersion = 1, - }) : client = client ?? MiddlewareClient(); - - String get apiPath => '/api/v$apiVersion'; - - Future sendSignUpCode(String email) async { - final r = await client.post( - Uri.parse('$apiPath/auth/send-sign-up-code'), - body: { - 'email': email, - }, - ); - if (r.statusCode != 201) { - throw Exception('Invalid reponse: ${r.statusCode}'); - } - } - - Future verifyCode(VerifyCode verifyCode) async { - final r = await client.post( - Uri.parse('$apiPath/auth/verify-code'), - body: verifyCode.toMap(), - ); - if (r.statusCode != 202) { - throw Exception('Invalid reponse: ${r.statusCode}'); - } else { - return Account.fromMap( - (jsonDecode(r.body) as Map)['account'] - as Map, - ); - } - } - - Future signUp(SignUp signUp) async { - final r = await client.post( - Uri.parse('$apiPath/auth/sign-up'), - body: signUp.toMap(), - ); - if (r.statusCode != 201) { - throw Exception('Invalid reponse: ${r.statusCode}'); - } else { - return Account.fromJson(r.body); - } - } - - Future signInWithPassword(Login login) async { - final r = await client.post( - Uri.parse('$apiPath/auth/sign-in-with-password'), - body: login.toMap(), - ); - if (r.statusCode != 200) { - throw Exception('Invalid reponse: ${r.statusCode}'); - } else { - return TokenSuccess.fromJson(r.body); - } - } - - // Future refresh() async { - // final r = await client.refresh(); - // return TokenSuccess.fromJson(r?.body ?? ''); - // } - - Future> getAccountList() async { - final r = await client.get( - Uri.parse('$apiPath/account'), - ); - if (r.statusCode != 200) { - throw Exception('Invalid reponse: ${r.statusCode}'); - } else { - final list = (jsonDecode(r.body) as Map)['founds'] - as List>; - final result = []; - for (final element in list) { - result.add(Account.fromMap(element)); - } - return result; - } - } -} - -void main(List args) async { - final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( - protocol: Protocols.http, - authority: 'localhost:80', - ), - ) - .addMiddleware(BodyToJsonMiddleware()) - .addMiddleware( - RefreshTokenAuthMiddleware( - authorizationEndpoint: '/api/v1/auth/sign-in-with-password', - tokenEndpoint: '/api/v1/auth/refresh', - accessTokenParser: (body) => body['access_token']! as String, - refreshTokenParser: (body) => body['refresh_token']! as String, - unauthorized: HttpStatus.forbidden, - ), - ) - .addMiddleware(SimpleLoggerMiddleware()); - - print(pipeline); - final client = MiddlewareClient(pipeline: pipeline); - - final api = FastAPI( - client: client, - ); - - await api.sendSignUpCode('git@pcl.ovh'); - // final verifiedAccount = await api.verifyCode( - // VerifyCode( - // email: 'git@pcl.ovh', - // verificationCode: '000000000', - // action: EmailVerificationAction.signUp, - // ), - // ); - // final registeredAccount = await api.signUp( - // SignUp(sessionId: verifiedAccount.sessionId ?? '', password: 'password'), - // ); - // final signedInAccount = await api.signInWithPassword( - // Login(email: 'git@pcl.ovh', password: 'password'), - // ); - final accountList = await api.getAccountList(); - print(accountList); -} diff --git a/packages/wyatt_http_client/example/pipeline.dart b/packages/wyatt_http_client/example/pipeline.dart deleted file mode 100644 index 7f261f39..00000000 --- a/packages/wyatt_http_client/example/pipeline.dart +++ /dev/null @@ -1,164 +0,0 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_http_client/src/middleware_client.dart'; -import 'package:wyatt_http_client/src/middlewares/body_to_json_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/simple_logger_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/unsafe_auth_middleware.dart'; -import 'package:wyatt_http_client/src/middlewares/uri_prefix_middleware.dart'; -import 'package:wyatt_http_client/src/pipeline.dart'; -import 'package:wyatt_http_client/src/utils/protocols.dart'; - -// class RequestMutatorMiddleware implements Middleware { -// @override -// Middleware? parent; - -// @override -// Middleware? child; - -// RequestMutatorMiddleware({ -// this.parent, -// this.child, -// }); - -// @override -// BaseRequest onRequest(BaseRequest request) { -// print('RequestMutator::OnRequest: ${request.method} -> ${request.url}'); -// return child?.onRequest(request) ?? request; -// } - -// @override -// BaseResponse onResponse(BaseResponse response) { -// final res = child?.onResponse(response) ?? response; -// print( -// 'RequestMutator::OnResponse: ${res.statusCode} -> ${res.contentLength} -// bytes', -// ); -// return res; -// } -// } - -// typedef Middleware = Handler Function(Handler innerHandler); - -// Middleware createMiddleware({ -// FutureOr Function(Request)? requestHandler, -// FutureOr Function(Response)? responseHandler, -// FutureOr Function(Object error, StackTrace)? errorHandler, -// }) { -// requestHandler ??= (request) => null; -// responseHandler ??= (response) => response; - -// FutureOr Function(Object, StackTrace)? onError; -// if (errorHandler != null) { -// onError = (error, stackTrace) { -// if (error is Exception) throw error; -// return errorHandler(error, stackTrace); -// }; -// } - -// return (Handler innerHandler) { -// return (request) { -// return Future.sync(() => requestHandler!(request)).then((response) { -// if (response != null) return response; - -// return Future.sync(() => innerHandler(request)) -// .then((response) => responseHandler!(response), onError: -// onError); -// }); -// }; -// }; -// } - -// extension MiddlewareX on Middleware { -// Middleware addMiddleware(Middleware other) => -// (Handler handler) => this(other(handler)); -// Handler addHandler(Handler handler) => this(handler); -// } - -// typedef Handler = FutureOr Function(Request request); - -// final headerMutator = createMiddleware( -// responseHandler: (response) { -// print(response.headers); -// return response; -// },); - -// class Pipeline { -// const Pipeline(); - -// Pipeline addMiddleware(Middleware middleware) => -// _Pipeline(middleware, addHandler); - -// Handler addHandler(Handler handler) => handler; - -// Middleware get middleware => addHandler; -// } - -// class _Pipeline extends Pipeline { -// final Middleware _middleware; -// final Middleware _parent; - -// _Pipeline(this._middleware, this._parent); - -// @override -// Handler addHandler(Handler handler) => _parent(_middleware(handler)); -// } - -Future main(List args) async { - final UnsafeAuthMiddleware auth = UnsafeAuthMiddleware(); - final Pipeline pipeline = Pipeline() - .addMiddleware( - UriPrefixMiddleware( - protocol: Protocols.http, - authority: 'localhost:80', - ), - ) - .addMiddleware(BodyToJsonMiddleware()) - .addMiddleware( - UnsafeAuthMiddleware( - username: 'wyatt', - password: 'motdepasse', - ), - ) - .addMiddleware(SimpleLoggerMiddleware()); - // .addMiddleware( - // RefreshTokenMiddleware( - // authorizationEndpoint: '/api/v1/account/test?action=authorize', - // tokenEndpoint: '/api/v1/account/test?action=refresh', - // accessTokenParser: (body) => body['access_token']! as String, - // refreshTokenParser: (body) => body['refresh_token']! as String, - // ), - // ); - - print(pipeline); - final client = MiddlewareClient(pipeline: pipeline); - await client.post( - Uri.parse('/api/v1/account/test'), - body: { - 'email': 'test@test.fr', - }, - ); - auth - ..username = 'username' - ..password = 'password'; - await client.post( - Uri.parse('/api/v1/account/test'), - body: { - 'email': 'test@test.fr', - }, - ); -} diff --git a/packages/wyatt_http_client/lib/src/middleware.dart b/packages/wyatt_http_client/lib/src/middleware.dart index 07cf6323..9f0c9d67 100644 --- a/packages/wyatt_http_client/lib/src/middleware.dart +++ b/packages/wyatt_http_client/lib/src/middleware.dart @@ -18,12 +18,21 @@ import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/models/middleware_response.dart'; +/// {@template middleware} +/// A middleware is a class that can intercept requests and responses +/// and modify them before they are sent to the server or before they +/// are returned to the client. +/// {@endtemplate} abstract class Middleware { - Middleware(); + /// {@macro middleware} + const Middleware(); + + /// The name of the middleware. String getName(); } mixin OnRequestMiddleware { + /// Performs an action before the request is sent to the server. Future onRequest( MiddlewareContext context, MiddlewareRequest request, @@ -31,6 +40,7 @@ mixin OnRequestMiddleware { } mixin OnResponseMiddleware { + /// Performs an action before the response is returned to the client. Future onResponse( MiddlewareContext context, MiddlewareResponse response, diff --git a/packages/wyatt_http_client/lib/src/middleware_client.dart b/packages/wyatt_http_client/lib/src/middleware_client.dart index 14cbd094..23c1f064 100644 --- a/packages/wyatt_http_client/lib/src/middleware_client.dart +++ b/packages/wyatt_http_client/lib/src/middleware_client.dart @@ -24,15 +24,23 @@ import 'package:wyatt_http_client/src/models/unfreezed_request.dart'; import 'package:wyatt_http_client/src/pipeline.dart'; import 'package:wyatt_http_client/src/utils/http_methods.dart'; +/// {@template middleware_client} +/// A custom [Client] implementation that allows you to intercept requests +/// and responses and modify them before they are sent to the server or +/// before they are returned to the client. +/// {@endtemplate} class MiddlewareClient extends BaseClient { + /// {@macro middleware_client} MiddlewareClient({ Pipeline? pipeline, Client? inner, }) : pipeline = pipeline ?? Pipeline(), - inner = inner ?? Client() { - print('Using Pipeline:\n$pipeline'); - } + inner = inner ?? Client(); + + /// The [Client] that will be used to send requests. final Client inner; + + /// The [Pipeline] that will be used to intercept requests and responses. final Pipeline pipeline; @override diff --git a/packages/wyatt_http_client/lib/src/middlewares/basic_auth_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/basic_auth_middleware.dart index 529e3113..37bf033a 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/basic_auth_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/basic_auth_middleware.dart @@ -22,14 +22,24 @@ import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/utils/authentication_methods.dart'; import 'package:wyatt_http_client/src/utils/header_keys.dart'; +/// {@template basic_auth_middleware} +/// A middleware that adds basic authentication to the request. +/// {@endtemplate} class BasicAuthMiddleware with OnRequestMiddleware implements Middleware { - BasicAuthMiddleware({ + /// {@macro basic_auth_middleware} + const BasicAuthMiddleware({ this.username, this.password, this.authenticationHeader = HeaderKeys.authorization, }); - String? username; - String? password; + + /// The username to use for authentication. + final String? username; + + /// The password to use for authentication. + final String? password; + + /// The header to use for authentication. final String authenticationHeader; @override @@ -43,10 +53,7 @@ class BasicAuthMiddleware with OnRequestMiddleware implements Middleware { if (username == null || password == null) { return request; } - print( - '${getName()}::OnRequest\n' - '>> Basic: ${base64Encode(utf8.encode('$username:$password'))}', - ); + final mutation = { authenticationHeader: '${AuthenticationMethods.basic} ' '${base64Encode(utf8.encode('$username:$password'))}', diff --git a/packages/wyatt_http_client/lib/src/middlewares/body_to_json_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/body_to_json_middleware.dart index a77048d8..e9aaaba7 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/body_to_json_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/body_to_json_middleware.dart @@ -20,7 +20,13 @@ import 'package:wyatt_http_client/src/middleware.dart'; import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; +/// {@template body_to_json_middleware} +/// A middleware that transforms the body in json if it's a [Map]. +/// {@endtemplate} class BodyToJsonMiddleware with OnRequestMiddleware implements Middleware { + /// {@macro body_to_json_middleware} + const BodyToJsonMiddleware(); + @override String getName() => 'BodyToJson'; @@ -29,11 +35,6 @@ class BodyToJsonMiddleware with OnRequestMiddleware implements Middleware { MiddlewareContext context, MiddlewareRequest request, ) async { - print( - '${getName()}::OnRequest\n' - '>> Transforms body in json if Map then update ' - 'headers with right content-type', - ); final mutation = { 'content-type': 'application/json; charset=utf-8', }; diff --git a/packages/wyatt_http_client/lib/src/middlewares/default_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/default_middleware.dart index 65b766ca..456a07b5 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/default_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/default_middleware.dart @@ -16,7 +16,13 @@ import 'package:wyatt_http_client/src/middleware.dart'; +/// {@template default_middleware} +/// A default middleware that does nothing. +/// {@endtemplate} class DefaultMiddleware implements Middleware { + /// {@macro default_middleware} + const DefaultMiddleware(); + @override String getName() => 'DefaultMiddleware'; } diff --git a/packages/wyatt_http_client/lib/src/middlewares/digest_auth_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/digest_auth_middleware.dart index c09d0423..55c17030 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/digest_auth_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/digest_auth_middleware.dart @@ -22,9 +22,13 @@ import 'package:wyatt_http_client/src/utils/digest_auth.dart'; import 'package:wyatt_http_client/src/utils/header_keys.dart'; import 'package:wyatt_http_client/src/utils/http_status.dart'; +/// {@template digest_auth_middleware} +/// A middleware that handles digest authentication. +/// {@endtemplate} class DigestAuthMiddleware with OnRequestMiddleware, OnResponseMiddleware implements Middleware { + /// {@macro digest_auth_middleware} DigestAuthMiddleware({ required this.username, required this.password, @@ -47,10 +51,6 @@ class DigestAuthMiddleware MiddlewareContext context, MiddlewareRequest request, ) async { - print( - '${getName()}::OnRequest\n' - '>> Digest ready: ${_digestAuth.isReady()}', - ); if (_digestAuth.isReady()) { final mutation = { authenticationHeader: _digestAuth.getAuthString( @@ -82,10 +82,6 @@ class DigestAuthMiddleware return MiddlewareResponse(httpResponse: newResponse); } } - print( - '${getName()}::OnResponse\n' - '>> Digest ready: ${_digestAuth.isReady()}', - ); return response; } } diff --git a/packages/wyatt_http_client/lib/src/middlewares/middlewares.dart b/packages/wyatt_http_client/lib/src/middlewares/middlewares.dart index 9c2b70b0..29bbf147 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/middlewares.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/middlewares.dart @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'access_token_auth_middleware.dart'; +// All built-in middlewares + export 'basic_auth_middleware.dart'; export 'body_to_json_middleware.dart'; export 'default_middleware.dart'; diff --git a/packages/wyatt_http_client/lib/src/middlewares/refresh_token_auth_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/refresh_token_auth_middleware.dart index 19f3f137..50f5005d 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/refresh_token_auth_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/refresh_token_auth_middleware.dart @@ -28,9 +28,14 @@ import 'package:wyatt_http_client/src/utils/http_status.dart'; typedef TokenParser = String Function(Map); +/// {@template refresh_token_auth_middleware} +/// A middleware that refreshes the access token when it expires. +/// This middleware is useful for OAuth2. +/// {@endtemplate} class RefreshTokenAuthMiddleware with OnRequestMiddleware, OnResponseMiddleware implements Middleware { + /// {@macro refresh_token_auth_middleware} RefreshTokenAuthMiddleware({ required this.authorizationEndpoint, required this.tokenEndpoint, @@ -113,11 +118,6 @@ class RefreshTokenAuthMiddleware MiddlewareContext context, MiddlewareRequest request, ) async { - print( - '${getName()}::OnRequest\n' - '>> accessToken: $accessToken\n' - '>> refreshToken: $refreshToken', - ); // Check if it is authorization if (context.originalRequest?.url == Uri.parse(authorizationEndpoint)) { return request; @@ -168,12 +168,6 @@ class RefreshTokenAuthMiddleware } } - print( - '${getName()}::OnResponse\n' - '>> accessToken: $accessToken\n' - '>> refreshToken: $refreshToken', - ); - if (response.status == unauthorized) { // Refresh MiddlewareRequest? newRequest = await refresh(context); diff --git a/packages/wyatt_http_client/lib/src/middlewares/simple_logger_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/simple_logger_middleware.dart index 8e2d2637..31492b8f 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/simple_logger_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/simple_logger_middleware.dart @@ -19,9 +19,15 @@ import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/models/middleware_response.dart'; +/// {@template simple_logger_middleware} +/// A simple logger middleware that logs the request and response. +/// {@endtemplate} class SimpleLoggerMiddleware with OnRequestMiddleware, OnResponseMiddleware implements Middleware { + /// {@macro simple_logger_middleware} + const SimpleLoggerMiddleware(); + @override String getName() => 'SimpleLogger'; @@ -30,11 +36,22 @@ class SimpleLoggerMiddleware MiddlewareContext context, MiddlewareRequest request, ) async { - print( - '${getName()}::OnRequest\n' - '>> ${request.method} ${request.url}\n' - '>> Headers: ${request.headers}\n>> Body: ${request.encodedBody}', - ); + final log = StringBuffer() + ..writeln('${getName()}::OnRequest') + ..writeln('>> ${request.method} ${request.url}'); + if (request.headers.isNotEmpty) { + log.writeln('>> Headers:'); + request.headers.forEach((key, value) { + log.writeln('>> $key: $value'); + }); + } + if (request.encodedBody.isNotEmpty) { + log + ..writeln('>> Body:') + ..writeln(request.encodedBody); + } + print(log); + return request; } @@ -43,12 +60,13 @@ class SimpleLoggerMiddleware MiddlewareContext context, MiddlewareResponse response, ) async { - print( - '${getName()}::OnResponse\n' - '>> Status: ${response.status.name.toUpperCase()}\n' - '>> Length: ${response.contentLength ?? '0'} bytes', - // '>> Body: ${response.body}', - ); + final log = StringBuffer() + ..writeln('${getName()}::OnResponse') + ..writeln('>> Status: ${response.status.name.toUpperCase()}') + ..writeln('>> Length: ${response.contentLength ?? '0'} bytes'); + + print(log); + return response; } } diff --git a/packages/wyatt_http_client/lib/src/middlewares/unsafe_auth_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/unsafe_auth_middleware.dart index 724d7211..f4481877 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/unsafe_auth_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/unsafe_auth_middleware.dart @@ -19,15 +19,20 @@ import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/utils/convert.dart'; +/// {@template unsafe_auth_middleware} +/// A middleware that appends the username and password to the URL. +/// +/// This is not recommended to use in production. +/// {@endtemplate} class UnsafeAuthMiddleware with OnRequestMiddleware implements Middleware { - UnsafeAuthMiddleware({ + const UnsafeAuthMiddleware({ this.username, this.password, this.usernameField = 'username', this.passwordField = 'password', }); - String? username; - String? password; + final String? username; + final String? password; final String usernameField; final String passwordField; @@ -45,10 +50,6 @@ class UnsafeAuthMiddleware with OnRequestMiddleware implements Middleware { } final Uri uri = request.url + '?$usernameField=$username&$passwordField=$password'; - print( - '${getName()}::OnRequest\n' - '>> Append: ?$usernameField=$username&$passwordField=$password', - ); request.modifyRequest(request.unfreezedRequest.copyWith(url: uri)); return request; } diff --git a/packages/wyatt_http_client/lib/src/middlewares/uri_prefix_middleware.dart b/packages/wyatt_http_client/lib/src/middlewares/uri_prefix_middleware.dart index 04c3232f..f02cff99 100644 --- a/packages/wyatt_http_client/lib/src/middlewares/uri_prefix_middleware.dart +++ b/packages/wyatt_http_client/lib/src/middlewares/uri_prefix_middleware.dart @@ -19,12 +19,20 @@ import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/utils/protocols.dart'; +/// {@template uri_prefix_middleware} +/// A middleware that adds a prefix to the request's URI. +/// {@endtemplate} class UriPrefixMiddleware with OnRequestMiddleware implements Middleware { - UriPrefixMiddleware({ + /// {@macro uri_prefix_middleware} + const UriPrefixMiddleware({ required this.protocol, required this.authority, }); + + /// The protocol of the prefix. final Protocols protocol; + + /// The authority of the prefix. final String? authority; @override @@ -36,11 +44,6 @@ class UriPrefixMiddleware with OnRequestMiddleware implements Middleware { MiddlewareRequest request, ) async { final Uri uri = Uri.parse('${protocol.scheme}$authority${request.url}'); - print( - '${getName()}::OnRequest\n' - '>> From: ${request.url}\n' - '>> To: $uri', - ); request.modifyRequest(request.unfreezedRequest.copyWith(url: uri)); return request; } diff --git a/packages/wyatt_http_client/lib/src/models/middleware_context.dart b/packages/wyatt_http_client/lib/src/models/middleware_context.dart index 503c2e3e..5071b39e 100644 --- a/packages/wyatt_http_client/lib/src/models/middleware_context.dart +++ b/packages/wyatt_http_client/lib/src/models/middleware_context.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -20,15 +19,12 @@ import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/models/middleware_response.dart'; import 'package:wyatt_http_client/src/pipeline.dart'; +/// {@template middleware_context} +/// A class that contains the context of the middleware. +/// {@endtemplate} class MiddlewareContext { - Pipeline pipeline; - MiddlewareClient client; - MiddlewareRequest? originalRequest; - MiddlewareRequest? lastRequest; - MiddlewareResponse? originalResponse; - MiddlewareResponse? lastResponse; - - MiddlewareContext({ + /// {@macro middleware_context} + const MiddlewareContext({ required this.pipeline, required this.client, this.originalRequest, @@ -37,6 +33,26 @@ class MiddlewareContext { this.lastResponse, }); + /// The pipeline that the middleware is in. + final Pipeline pipeline; + + /// The client that the middleware is in. + final MiddlewareClient client; + + /// The original request that the middleware is in. + final MiddlewareRequest? originalRequest; + + /// The last request that the middleware is in. + final MiddlewareRequest? lastRequest; + + /// The original response that the middleware is in. + final MiddlewareResponse? originalResponse; + + /// The last response that the middleware is in. + final MiddlewareResponse? lastResponse; + + /// Create a copy of this [MiddlewareContext] with the given fields replaced + /// with the new values. MiddlewareContext copyWith({ Pipeline? pipeline, MiddlewareClient? client, diff --git a/packages/wyatt_http_client/lib/src/models/middleware_request.dart b/packages/wyatt_http_client/lib/src/models/middleware_request.dart index 333d3177..e7c93703 100644 --- a/packages/wyatt_http_client/lib/src/models/middleware_request.dart +++ b/packages/wyatt_http_client/lib/src/models/middleware_request.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -22,24 +21,43 @@ import 'package:wyatt_http_client/src/models/unfreezed_request.dart'; import 'package:wyatt_http_client/src/utils/convert.dart'; import 'package:wyatt_http_client/src/utils/request_utils.dart'; +/// {@template middleware_request} +/// A class that represents a middleware request. +/// {@endtemplate} class MiddlewareRequest { - UnfreezedRequest unfreezedRequest; - Request _httpRequest; - - Request get request => _httpRequest; - - // Proxy - String get method => _httpRequest.method; - Uri get url => _httpRequest.url; - Map get headers => _httpRequest.headers; - Encoding get encoding => _httpRequest.encoding; - String get encodedBody => _httpRequest.body; - Object? get body => unfreezedRequest.body; - + /// {@macro middleware_request} MiddlewareRequest({ required this.unfreezedRequest, }) : _httpRequest = Request(unfreezedRequest.method, unfreezedRequest.url); + /// The unfreezed request. + UnfreezedRequest unfreezedRequest; + + Request _httpRequest; + + /// The http request. (Read-only) + Request get request => _httpRequest; + + /// The request method (proxy, read-only). + String get method => _httpRequest.method; + + /// The request url (proxy, read-only). + Uri get url => _httpRequest.url; + + /// The request headers (proxy, read-only). + Map get headers => _httpRequest.headers; + + /// The request body (proxy, read-only). + Encoding get encoding => _httpRequest.encoding; + + /// The request body (proxy, read-only). + String get encodedBody => _httpRequest.body; + + /// The request body (proxy, read-only). + Object? get body => unfreezedRequest.body; + + /// Copies this request and returns a new request with the given + /// [unfreezedRequest]. MiddlewareRequest copyWith({ UnfreezedRequest? unfreezedRequest, }) => @@ -47,6 +65,7 @@ class MiddlewareRequest { unfreezedRequest: unfreezedRequest ?? this.unfreezedRequest, ); + /// Modifies the request with the given [unfreezedRequest]. void modifyRequest(UnfreezedRequest unfreezedRequest) { String? body; if (unfreezedRequest.body != null) { @@ -72,6 +91,8 @@ class MiddlewareRequest { this.unfreezedRequest = unfreezedRequest; } + /// Applies the changes made to the request by modifying it with the + /// [unfreezedRequest]. void apply() { modifyRequest(unfreezedRequest); } diff --git a/packages/wyatt_http_client/lib/src/models/middleware_response.dart b/packages/wyatt_http_client/lib/src/models/middleware_response.dart index 500c17c3..19781901 100644 --- a/packages/wyatt_http_client/lib/src/models/middleware_response.dart +++ b/packages/wyatt_http_client/lib/src/models/middleware_response.dart @@ -1,4 +1,3 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -18,12 +17,25 @@ import 'package:http/http.dart'; import 'package:wyatt_http_client/src/utils/http_status.dart'; +/// {@template middleware_response} +/// A class that represents a middleware response. +/// {@endtemplate} class MiddlewareResponse { - BaseResponse httpResponse; + /// {@macro middleware_response} + const MiddlewareResponse({ + required this.httpResponse, + }); - // Proxy + /// {@macro middleware_response} + final BaseResponse httpResponse; + + /// The status code of the response. (proxy) int get statusCode => httpResponse.statusCode; + + /// The status of the response. (proxy) HttpStatus get status => HttpStatus.from(statusCode); + + /// The body of the response. (proxy or empty string) String get body { if (httpResponse is Response) { return (httpResponse as Response).body; @@ -32,13 +44,13 @@ class MiddlewareResponse { } } + /// The content length of the response. (proxy) int? get contentLength => httpResponse.contentLength; + + /// The headers of the response. (proxy) Map get headers => httpResponse.headers; - MiddlewareResponse({ - required this.httpResponse, - }); - + /// Returns a copy of this response with the given [httpResponse]. MiddlewareResponse copyWith({ BaseResponse? httpResponse, }) => diff --git a/packages/wyatt_http_client/lib/src/models/unfreezed_request.dart b/packages/wyatt_http_client/lib/src/models/unfreezed_request.dart index d29c15d8..6779a5b6 100644 --- a/packages/wyatt_http_client/lib/src/models/unfreezed_request.dart +++ b/packages/wyatt_http_client/lib/src/models/unfreezed_request.dart @@ -16,20 +16,38 @@ import 'dart:convert'; +/// {@template unfreezed_request} +/// A class that represents an unfreezed request. +/// It is used to unfreeze a Request object, and allows you to +/// modify the request before sending it. +/// {@endtemplate} class UnfreezedRequest { - UnfreezedRequest({ + /// {@macro unfreezed_request} + const UnfreezedRequest({ required this.method, required this.url, this.headers, this.body, this.encoding, }); + + /// The request method. final String method; + + /// The request url. final Uri url; + + /// The request headers. final Map? headers; + + /// The request body. final Object? body; + + /// The request encoding. final Encoding? encoding; + /// Copies this request and returns a new request with the given [method], + /// [url], [headers], [body] and [encoding]. UnfreezedRequest copyWith({ String? method, Uri? url, diff --git a/packages/wyatt_http_client/lib/src/pipeline.dart b/packages/wyatt_http_client/lib/src/pipeline.dart index 3cebc400..d68e7e39 100644 --- a/packages/wyatt_http_client/lib/src/pipeline.dart +++ b/packages/wyatt_http_client/lib/src/pipeline.dart @@ -19,20 +19,27 @@ import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/models/middleware_response.dart'; +/// {@template pipeline} +/// A [Pipeline] is a list of [Middleware]s that are executed in order. +/// {@endtemplate} class Pipeline { + /// {@macro pipeline} Pipeline() : _middlewares = []; + + /// {@macro pipeline} Pipeline.fromIterable(Iterable middlewares) : _middlewares = middlewares.toList(); + final List _middlewares; + /// The length of the [Pipeline]. + /// + /// This is the number of [Middleware]s in the [Pipeline]. int get length => _middlewares.length; /// Add a [Middleware] to this [Pipeline] - Pipeline addMiddleware(Middleware middleware) { + void addMiddleware(Middleware middleware) { _middlewares.add(middleware); - // TODO(hpcl): use Dart cascades instead of returning this - // ignore: avoid_returning_this - return this; } /// Create new [Pipeline] from the start or end to a specified [Middleware]. @@ -57,11 +64,15 @@ class Pipeline { return Pipeline.fromIterable(fromEnd ? nodes.reversed : nodes); } + /// Call the [onRequest] method of all [OnRequestMiddleware]s in the + /// [Pipeline]. + /// + /// The [MiddlewareRequest] returned by the last [OnRequestMiddleware] is + /// returned. Future onRequest( MiddlewareContext context, MiddlewareRequest request, ) async { - print('\n\nNEW REQUEST\n'); MiddlewareRequest req = request..apply(); MiddlewareContext ctx = context.copyWith(lastRequest: req); for (final middleware in _middlewares) { @@ -73,11 +84,15 @@ class Pipeline { return req; } + /// Call the [onResponse] method of all [OnResponseMiddleware]s in the + /// [Pipeline]. + /// + /// The [MiddlewareResponse] returned by the last [OnResponseMiddleware] is + /// returned. Future onResponse( MiddlewareContext context, MiddlewareResponse response, ) async { - print('\n\nNEW RESPONSE\n'); MiddlewareResponse res = response; MiddlewareContext ctx = context.copyWith(lastResponse: res); for (final middleware in _middlewares.reversed) { diff --git a/packages/wyatt_http_client/lib/src/utils/authentication_methods.dart b/packages/wyatt_http_client/lib/src/utils/authentication_methods.dart index ef73c15f..d8f028c2 100644 --- a/packages/wyatt_http_client/lib/src/utils/authentication_methods.dart +++ b/packages/wyatt_http_client/lib/src/utils/authentication_methods.dart @@ -14,8 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines some authentication methods abstract class AuthenticationMethods { + /// The `Basic` authentication method. static const String basic = 'Basic'; + + /// The `Bearer` authentication method. static const String bearer = 'Bearer'; + + /// The `Digest` authentication method. static const String digest = 'Digest'; } diff --git a/packages/wyatt_http_client/lib/src/utils/convert.dart b/packages/wyatt_http_client/lib/src/utils/convert.dart index 1f287757..93c86d59 100644 --- a/packages/wyatt_http_client/lib/src/utils/convert.dart +++ b/packages/wyatt_http_client/lib/src/utils/convert.dart @@ -16,7 +16,11 @@ import 'dart:convert'; -class Convert { +/// Defines some convert functions. +abstract class Convert { + /// Converts a list of bytes to a hex string. + /// + /// If [upperCase] is `true`, the hex string will be in uppercase. static String toHex(List bytes, {bool upperCase = false}) { final buffer = StringBuffer(); for (final int part in bytes) { @@ -32,6 +36,11 @@ class Convert { } } + /// Converts a map to a query string. + /// + /// If [encoding] is `null`, the default encoding is `utf8`. + /// + /// For example, the map `{a: 1, b: 2}` will be converted to `a=1&b=2`. static String mapToQuery(Map map, {Encoding? encoding}) { final pairs = >[]; map.forEach( @@ -45,6 +54,7 @@ class Convert { } extension UriX on Uri { + /// Returns a new [Uri] by appending the given [path] to this [Uri]. Uri operator +(String path) { final thisPath = toString(); return Uri.parse(thisPath + path); diff --git a/packages/wyatt_http_client/lib/src/utils/crypto.dart b/packages/wyatt_http_client/lib/src/utils/crypto.dart index f27d08a7..bf7fa5a6 100644 --- a/packages/wyatt_http_client/lib/src/utils/crypto.dart +++ b/packages/wyatt_http_client/lib/src/utils/crypto.dart @@ -18,7 +18,8 @@ import 'dart:convert'; import 'package:crypto/crypto.dart'; -class Crypto { +/// Defines some crypto functions. +abstract class Crypto { /// Hash a string using MD5 static String md5Hash(String data) { final content = const Utf8Encoder().convert(data); diff --git a/packages/wyatt_http_client/lib/src/utils/delay.dart b/packages/wyatt_http_client/lib/src/utils/delay.dart index 3ca50947..cc9d4193 100644 --- a/packages/wyatt_http_client/lib/src/utils/delay.dart +++ b/packages/wyatt_http_client/lib/src/utils/delay.dart @@ -17,7 +17,9 @@ import 'dart:core'; import 'dart:math'; +/// Defines some delay functions. abstract class Delay { + /// Returns a delay based on the [attempt]. static Duration getRetryDelay(int attempt) { assert(attempt >= 0, 'attempt cannot be negative'); if (attempt <= 0) { diff --git a/packages/wyatt_http_client/lib/src/utils/digest_auth.dart b/packages/wyatt_http_client/lib/src/utils/digest_auth.dart index ba16c0aa..065eeef0 100644 --- a/packages/wyatt_http_client/lib/src/utils/digest_auth.dart +++ b/packages/wyatt_http_client/lib/src/utils/digest_auth.dart @@ -19,12 +19,13 @@ import 'dart:math'; import 'package:wyatt_http_client/src/utils/convert.dart'; import 'package:wyatt_http_client/src/utils/crypto.dart'; +/// A class for digest authentication. class DigestAuth { // request counter DigestAuth(this.username, this.password); - String username; - String password; + final String username; + final String password; // must get from first response String? _algorithm; diff --git a/packages/wyatt_http_client/lib/src/utils/header_keys.dart b/packages/wyatt_http_client/lib/src/utils/header_keys.dart index 9fe72ce8..c1c9e986 100644 --- a/packages/wyatt_http_client/lib/src/utils/header_keys.dart +++ b/packages/wyatt_http_client/lib/src/utils/header_keys.dart @@ -14,8 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines some header keys. abstract class HeaderKeys { + /// The `Authorization` header key. static const String authorization = 'Authorization'; + + /// The `WWW-Authenticate` header key. static const String wwwAuthenticate = 'WWW-Authenticate'; + + /// The `Content-Type` header key. static const String contentType = 'Content-Type'; } diff --git a/packages/wyatt_http_client/lib/src/utils/http_methods.dart b/packages/wyatt_http_client/lib/src/utils/http_methods.dart index 7b0a4c7a..efef38c4 100644 --- a/packages/wyatt_http_client/lib/src/utils/http_methods.dart +++ b/packages/wyatt_http_client/lib/src/utils/http_methods.dart @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines http verb methods. enum HttpMethods { head('HEAD'), get('GET'), @@ -24,5 +25,8 @@ enum HttpMethods { const HttpMethods(this.method); + /// Returns the method of the http verb. + /// + /// For example, the method of [HttpMethods.get] is `GET`. final String method; } diff --git a/packages/wyatt_http_client/lib/src/utils/http_status.dart b/packages/wyatt_http_client/lib/src/utils/http_status.dart index e5360309..f5a5c488 100644 --- a/packages/wyatt_http_client/lib/src/utils/http_status.dart +++ b/packages/wyatt_http_client/lib/src/utils/http_status.dart @@ -83,6 +83,7 @@ enum HttpStatus { const HttpStatus(this.statusCode); + /// Returns the [HttpStatus] with the given [statusCode]. factory HttpStatus.from(int status) => HttpStatus.values.firstWhere((element) => element.statusCode == status); @@ -98,13 +99,18 @@ enum HttpStatus { return false; } + /// Checks if the status code is in the range of 100-199. bool isInfo() => statusCode >= 100 && statusCode < 200; + /// Checks if the status code is in the range of 200-299. bool isSuccess() => statusCode >= 200 && statusCode < 300; + /// Checks if the status code is in the range of 300-399. bool isRedirection() => statusCode >= 300 && statusCode < 400; + /// Checks if the status code is in the range of 400-499. bool isClientError() => statusCode >= 400 && statusCode < 500; + /// Checks if the status code is in the range of 500-599. bool isServerError() => statusCode >= 500 && statusCode < 600; } diff --git a/packages/wyatt_http_client/lib/src/utils/protocols.dart b/packages/wyatt_http_client/lib/src/utils/protocols.dart index 97b9d5f3..bf41a5d6 100644 --- a/packages/wyatt_http_client/lib/src/utils/protocols.dart +++ b/packages/wyatt_http_client/lib/src/utils/protocols.dart @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines few protocols enum Protocols { http, https; + /// Returns the scheme of the protocol. + /// + /// For example, the scheme of [Protocols.http] is `http://`. String get scheme => '$name://'; } diff --git a/packages/wyatt_http_client/lib/src/utils/request_utils.dart b/packages/wyatt_http_client/lib/src/utils/request_utils.dart index b50c0063..01794757 100644 --- a/packages/wyatt_http_client/lib/src/utils/request_utils.dart +++ b/packages/wyatt_http_client/lib/src/utils/request_utils.dart @@ -16,6 +16,7 @@ import 'package:http/http.dart'; +/// Defines some request utils. abstract class RequestUtils { static Request _copyNormalRequestWith( Request original, { @@ -38,6 +39,9 @@ abstract class RequestUtils { return request; } + /// Copies the given [original] request and returns a new request with the + /// given [method], [url], [headers], [maxRedirects], [followRedirects], + /// [persistentConnection] and [body]. static BaseRequest copyRequestWith( BaseRequest original, { String? method, @@ -77,6 +81,8 @@ abstract class RequestUtils { return request; } + /// Copies the given [original] request and returns a new request. + /// This method is useful when you want to modify the request static BaseRequest copyRequest(BaseRequest original) { if (original is Request) { return _copyNormalRequest(original); diff --git a/packages/wyatt_http_client/pubspec.yaml b/packages/wyatt_http_client/pubspec.yaml index 699732db..357e00a8 100644 --- a/packages/wyatt_http_client/pubspec.yaml +++ b/packages/wyatt_http_client/pubspec.yaml @@ -3,6 +3,8 @@ description: A Dart client for RESTful APIs with authentication. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_http_client version: 1.2.0 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: sdk: '>=2.17.0 <3.0.0' @@ -12,7 +14,5 @@ dependencies: dev_dependencies: wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.4.1 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.4.1 diff --git a/packages/wyatt_i18n/.gitignore b/packages/wyatt_i18n/.gitignore deleted file mode 100644 index 3cceda55..00000000 --- a/packages/wyatt_i18n/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ - -# Avoid committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_i18n/.gitignore b/packages/wyatt_i18n/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_i18n/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_i18n/.pubignore b/packages/wyatt_i18n/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_i18n/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_i18n/AUTHORS b/packages/wyatt_i18n/AUTHORS deleted file mode 100644 index 8a49779b..00000000 --- a/packages/wyatt_i18n/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval \ No newline at end of file diff --git a/packages/wyatt_i18n/AUTHORS b/packages/wyatt_i18n/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_i18n/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_i18n/LICENSE b/packages/wyatt_i18n/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_i18n/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_i18n/LICENSE b/packages/wyatt_i18n/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_i18n/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_i18n/README.md b/packages/wyatt_i18n/README.md index 09cd8b61..b878a833 100644 --- a/packages/wyatt_i18n/README.md +++ b/packages/wyatt_i18n/README.md @@ -16,7 +16,7 @@ * along with this program. If not, see . --> -# Flutter - Wyatt I18n +# Wyatt I18n

Style: Wyatt Analysis diff --git a/packages/wyatt_i18n/analysis_options.yaml b/packages/wyatt_i18n/analysis_options.yaml index 265c79a8..3302c602 100644 --- a/packages/wyatt_i18n/analysis_options.yaml +++ b/packages/wyatt_i18n/analysis_options.yaml @@ -1,4 +1,5 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml + analyzer: plugins: - dart_code_metrics diff --git a/packages/wyatt_i18n/pubspec.yaml b/packages/wyatt_i18n/pubspec.yaml index 23c658ea..a0336a93 100644 --- a/packages/wyatt_i18n/pubspec.yaml +++ b/packages/wyatt_i18n/pubspec.yaml @@ -1,17 +1,19 @@ name: wyatt_i18n -description: A package by wyatt studio. +description: Library to handle internationalization in Flutter apps. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_i18n version: 1.0.0 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: sdk: ">=2.19.0 <3.0.0" dependencies: collection: ^1.17.0 equatable: ^2.0.5 - flutter: {sdk: flutter} + flutter: { sdk: flutter } flutter_bloc: ^8.1.2 - flutter_localizations: {sdk: flutter} + flutter_localizations: { sdk: flutter } http: ^0.13.5 intl: ^0.17.0 path: ^1.8.0 @@ -20,26 +22,22 @@ dependencies: hosted: url: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ name: wyatt_architecture - version: 0.1.0+1 + version: ^0.1.0+1 wyatt_bloc_helper: hosted: url: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ name: wyatt_bloc_helper - version: 2.0.0 + version: ^2.0.0 wyatt_type_utils: hosted: url: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ name: wyatt_type_utils - version: 0.0.4 + version: ^0.0.4 yaml: ^3.1.1 dev_dependencies: - flutter_test: {sdk: flutter} + flutter_test: { sdk: flutter } dart_code_metrics: ^5.5.1 wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub version: ^2.4.1 - -# The following section is specific to Flutter. -flutter: - uses-material-design: true diff --git a/packages/wyatt_notification_bloc/.gitignore b/packages/wyatt_notification_bloc/.gitignore deleted file mode 100644 index 65c34dc8..00000000 --- a/packages/wyatt_notification_bloc/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_notification_bloc/.gitignore b/packages/wyatt_notification_bloc/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_notification_bloc/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_notification_bloc/.pubignore b/packages/wyatt_notification_bloc/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_notification_bloc/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_notification_bloc/AUTHORS b/packages/wyatt_notification_bloc/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_notification_bloc/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_notification_bloc/LICENSE b/packages/wyatt_notification_bloc/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_notification_bloc/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_type_utils/.gitignore b/packages/wyatt_type_utils/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_type_utils/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_type_utils/.gitignore b/packages/wyatt_type_utils/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_type_utils/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_type_utils/.pubignore b/packages/wyatt_type_utils/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_type_utils/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_type_utils/AUTHORS b/packages/wyatt_type_utils/AUTHORS deleted file mode 100644 index f9506138..00000000 --- a/packages/wyatt_type_utils/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file diff --git a/packages/wyatt_type_utils/AUTHORS b/packages/wyatt_type_utils/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_type_utils/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_type_utils/LICENSE b/packages/wyatt_type_utils/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_type_utils/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_type_utils/LICENSE b/packages/wyatt_type_utils/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_type_utils/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_type_utils/README.md b/packages/wyatt_type_utils/README.md index 75750496..b36d5c1f 100644 --- a/packages/wyatt_type_utils/README.md +++ b/packages/wyatt_type_utils/README.md @@ -1,5 +1,5 @@ - - -# Dart - Wyatt Type Utils +# Wyatt Type Utils

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Dart & Flutter

-Type Utils for Dart & Flutter. +Either, Option and other useful types and extensions for Dart (and Flutter). ## Option\ @@ -62,8 +58,8 @@ print('`rand` contains 10 ? => ${rand.contains(10)}'); *E.g. null reference exception or index out of bounds are not related to domain - they rather indicate a defect.* Either is defined as a generic type with two branches -- success with **T** -- failure with **E** +* success with **T** +* failure with **E** It can appear in two forms, where it contains an object of **Ok**, or where it contains an object of **Err**. It cannot appear in both states at once, or in none of them. Therefore, if one possesses an **Result** instance, it either contains a successfully produced result, or contains an error object. @@ -95,20 +91,20 @@ print(myList); // prints '[42, 16]' This package also provides extensions for Dart types. -- Object - - isNull - - isNotNull - - log -- Iterable - - isNullOrEmpty - - isNotNullOrEmpty - - For bytes iterables +* Object + + isNull + + isNotNull + + log +* Iterable + + isNullOrEmpty + + isNotNullOrEmpty + + For bytes iterables - toTypedList - toStr -- String - - isNullOrEmpty - - isNotNullOrEmpty - - toBytes +* String + + isNullOrEmpty + + isNotNullOrEmpty + + toBytes String 🔁 Uint8List works with encoding: @@ -118,27 +114,27 @@ final Uint8List bytes = myString.toBytes(from : Encoding.utf16); print(bytes.toStr(to : Encoding.utf16)); // prints 'abc' ``` -- DateTime - - fromSecondsSinceEpoch - - secondsSinceEpoch - - timestamp - - tomorrow - - yesterday - - today - - add/sub/set - - nextDay - - previousDay - - nextMonth - - previousMonth - - nextYear - - previousYear - - nextWeek - - previousWeek - - isFuture - - isPast - - isLeapYear - - format - - operators +* DateTime + + fromSecondsSinceEpoch + + secondsSinceEpoch + + timestamp + + tomorrow + + yesterday + + today + + add/sub/set + + nextDay + + previousDay + + nextMonth + + previousMonth + + nextYear + + previousYear + + nextWeek + + previousWeek + + isFuture + + isPast + + isLeapYear + + format + + operators The date formatter works with `String` formatter: @@ -146,3 +142,11 @@ The date formatter works with `String` formatter: final DateTime date = DateTime(1999, 6, 30); print(date.format([dd, '/', mm, '/', yy])); // prints '30/06/99' ``` + +Allow comparison between nullable numbers: + +```dart +final int? a = 10; +final int? b = 20; +print(a < b); // prints 'true' +``` diff --git a/packages/wyatt_type_utils/lib/src/either/option.dart b/packages/wyatt_type_utils/lib/src/either/option.dart index d97ed2ac..3502984f 100644 --- a/packages/wyatt_type_utils/lib/src/either/option.dart +++ b/packages/wyatt_type_utils/lib/src/either/option.dart @@ -171,8 +171,11 @@ abstract class Option extends _EitherBase { } } +/// {@template value} +/// Contains the non-null value of the [Option]. +/// {@endtemplate} class Value extends Option with _Left { - /// {@macro ok} + /// {@macro value} const Value(this.value) : super._(); final T value; @@ -236,8 +239,11 @@ class Value extends Option with _Left { _EitherBase _or(_EitherBase res) => this as _EitherBase; } +/// {@template none} +/// Contains no value. +/// {@endtemplate} class None extends Option with _Right { - /// {@macro ok} + /// {@macro none} const None() : super._(); @override diff --git a/packages/wyatt_type_utils/lib/src/extensions/encoding.dart b/packages/wyatt_type_utils/lib/src/extensions/encoding.dart index 4a6fb8f7..5289d5f0 100644 --- a/packages/wyatt_type_utils/lib/src/extensions/encoding.dart +++ b/packages/wyatt_type_utils/lib/src/extensions/encoding.dart @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines different text encoding types. enum Encoding { utf8, utf16, diff --git a/packages/wyatt_type_utils/lib/src/extensions/extensions.dart b/packages/wyatt_type_utils/lib/src/extensions/extensions.dart new file mode 100644 index 00000000..be624333 --- /dev/null +++ b/packages/wyatt_type_utils/lib/src/extensions/extensions.dart @@ -0,0 +1,22 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'date_time_extension.dart'; +export 'encoding.dart'; +export 'iterable_extension.dart'; +export 'num_extension.dart'; +export 'object_extension.dart'; +export 'string_extension.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart b/packages/wyatt_type_utils/lib/src/extensions/num_extension.dart similarity index 97% rename from packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart rename to packages/wyatt_type_utils/lib/src/extensions/num_extension.dart index abe45b91..66979260 100644 --- a/packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart +++ b/packages/wyatt_type_utils/lib/src/extensions/num_extension.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify diff --git a/packages/wyatt_type_utils/lib/src/src.dart b/packages/wyatt_type_utils/lib/src/src.dart index 34d55694..c1d65c3c 100644 --- a/packages/wyatt_type_utils/lib/src/src.dart +++ b/packages/wyatt_type_utils/lib/src/src.dart @@ -15,9 +15,5 @@ // along with this program. If not, see . export 'either/either_base.dart'; -export 'extensions/date_time_extension.dart'; -export 'extensions/encoding.dart'; -export 'extensions/iterable_extension.dart'; -export 'extensions/object_extension.dart'; -export 'extensions/string_extension.dart'; +export 'extensions/extensions.dart'; export 'pair/pair.dart'; diff --git a/packages/wyatt_type_utils/pubspec.yaml b/packages/wyatt_type_utils/pubspec.yaml index c74145af..94d5faf7 100644 --- a/packages/wyatt_type_utils/pubspec.yaml +++ b/packages/wyatt_type_utils/pubspec.yaml @@ -1,16 +1,16 @@ name: wyatt_type_utils -description: Either, Option and other useful types. +description: Either, Option and other useful types and extensions. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_type_utils version: 0.0.4 publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: - sdk: '>=2.17.0 <3.0.0' + sdk: ">=2.17.0 <3.0.0" dev_dependencies: test: ^1.22.0 - + wyatt_analysis: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub - version: ^2.4.1 \ No newline at end of file + version: ^2.4.1 diff --git a/packages/wyatt_ui_components/.gitignore b/packages/wyatt_ui_components/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_ui_components/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_ui_components/.gitignore b/packages/wyatt_ui_components/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_ui_components/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_ui_components/.pubignore b/packages/wyatt_ui_components/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_ui_components/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_ui_components/AUTHORS b/packages/wyatt_ui_components/AUTHORS deleted file mode 100644 index f9506138..00000000 --- a/packages/wyatt_ui_components/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file diff --git a/packages/wyatt_ui_components/AUTHORS b/packages/wyatt_ui_components/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_ui_components/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_ui_components/LICENSE b/packages/wyatt_ui_components/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_ui_components/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_ui_components/LICENSE b/packages/wyatt_ui_components/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_ui_components/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_ui_components/README.md b/packages/wyatt_ui_components/README.md index 4c2d773d..5fedb940 100644 --- a/packages/wyatt_ui_components/README.md +++ b/packages/wyatt_ui_components/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,48 +16,35 @@ * along with this program. If not, see . --> -# Flutter - Wyatt Ui Components +# Wyatt UI Components

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Flutter

-Wyatt Ui Components for Flutter. +Wyatt UI Components for Flutter. This package defines all the components used in Wyatt Studio with their set of properties. But there is no implementation of the components. You have to create your own or check out [Wyatt UI Kit](https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_kit) package. ## Usage ### Configuration -First create all your custom components in `core/design_system/components/`folder. For exemple : +First create all your custom components in `domain/entities` folder. For exemple : -├── design_system -│ ├── components +``` +├── domain +│ ├── entities │ │ ├── custom_app_bar.dart │ │ ├── custom_bottom_navigation_bar.dart │ │ └── ... │ └── ... └── ... - -You have to override `confgure` method. - -Then create AppComponentTheme class in `core/design_system/` folder and add all your components. For Example : - -```dart -class AppThemeComponent { - static ComponentThemeData get components => ComponentThemeData.raw( - appBar: const CustomAppBar(), - bottomNavigationBar: CustomBottomNavigationBar( - onTap: (context, index) { - print('$index'); - }, - ), - ); -} ``` +> Run `flutter pub run build_runner build` to generate your components. + +Then, add your components to `ComponentThemeData` class. + ### Provider In you main file, before calling router, call `ComponentTheme` widget and give your app as child. For example : @@ -72,7 +59,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) => ComponentTheme( - themDataWidget: AppThemeComponent.components, + componentThemeWidget: AppThemeComponent.components, child: MaterialApp( title: 'Wyatt Ui Layout Example', theme: ThemeData( @@ -102,12 +89,32 @@ For example : ) ``` -If you need specific settings, or pass parameters to your component, call `configure` method. It will use default paramters you've passed in your app comppnent theme file, and update the parameter you need to change. For example : +If you need specific settings, or pass parameters to your component, call `copyWith.call` method. ```dart @override Widget build(BuildContext context) => Scaffold( - appBar: context.components.appBar.configure({title:'New Title !}), + appBar: context.components.appBar.copyWith.call({title: 'New Title !'}), body: ... ) ``` + +## Development + +> Common to this, and Wyatt UI Kit packages. + +Add a new component : + +**Wyatt UI Components side** + + 1. Create a new file in `lib/src/domain/entities` folder. + 2. Add your component class. + 3. Add your component class to `ComponentThemeData` abstract class. + 4. Run `flutter pub run build_runner build` to generate your component proxy properties. + +**Wyatt UI Kit side** + 1. Create a new file in `lib/src/components` folder. + 2. Add your component class, styles, (and logic if needed) + 3. Run `flutter pub run build_runner build` to generate your component copy with method. + 4. Add a theme extension to your component class in `lib/src/domain/` + 5. Add your component class `wyattComponentThemeData` static property in `lib/src/features/wyatt_component_theme_data.dart` diff --git a/packages/wyatt_ui_components/analysis_options.yaml b/packages/wyatt_ui_components/analysis_options.yaml index 90d6bd51..8c9daa4e 100644 --- a/packages/wyatt_ui_components/analysis_options.yaml +++ b/packages/wyatt_ui_components/analysis_options.yaml @@ -1,17 +1 @@ -# Copyright (C) 2023 WYATT GROUP -# Please see the AUTHORS file for details. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - include: package:wyatt_analysis/analysis_options.flutter.yaml diff --git a/packages/wyatt_ui_components/lib/src/core/enums/status_state.dart b/packages/wyatt_ui_components/lib/src/core/enums/status_state.dart index 878899f6..9add284a 100644 --- a/packages/wyatt_ui_components/lib/src/core/enums/status_state.dart +++ b/packages/wyatt_ui_components/lib/src/core/enums/status_state.dart @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Defines status states enum StatusState { initial, success, diff --git a/packages/wyatt_ui_components/lib/src/core/extensions/build_context_extensions.dart b/packages/wyatt_ui_components/lib/src/core/extensions/build_context_extensions.dart index be5e6045..b00fdb3f 100644 --- a/packages/wyatt_ui_components/lib/src/core/extensions/build_context_extensions.dart +++ b/packages/wyatt_ui_components/lib/src/core/extensions/build_context_extensions.dart @@ -18,5 +18,13 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/src/features/features.dart'; extension ThemeComponentBuildContext on BuildContext { + /// Returns the [ComponentThemeData] of the current [BuildContext]. + /// + /// Throws an [AssertionError] if the current [BuildContext] does not contain + /// a [ComponentTheme]. ComponentThemeData get components => ComponentTheme.of(this); + + /// Returns the [ComponentThemeData] of the current [BuildContext] if it + /// exists. + ComponentThemeData? get maybeComponents => ComponentTheme.maybeOf(this); } diff --git a/packages/wyatt_ui_components/lib/src/core/mixins/copy_with_mixin.dart b/packages/wyatt_ui_components/lib/src/core/mixins/copy_with_mixin.dart index cd7bd5a9..728622c5 100644 --- a/packages/wyatt_ui_components/lib/src/core/mixins/copy_with_mixin.dart +++ b/packages/wyatt_ui_components/lib/src/core/mixins/copy_with_mixin.dart @@ -15,5 +15,8 @@ // along with this program. If not, see . mixin CopyWithMixin { + /// Returns a copy of the current object with the specified properties + /// overridden by the specified values. + /// You have to call the `.call()` method on the returned object. Proxy get copyWith; } diff --git a/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart b/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart index d64ac9a3..1a3aa44e 100644 --- a/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart +++ b/packages/wyatt_ui_components/lib/src/core/utils/multi_color.dart @@ -16,13 +16,20 @@ import 'package:flutter/widgets.dart'; +/// {@template multi_color} +/// A class that can hold a [Color] or a [List] of [Color]s. +/// {@endtemplate} class MultiColor { + /// {@macro multi_color} const MultiColor(this._colors) : _color = null; + + /// {@macro multi_color} const MultiColor.single(this._color) : _colors = null; final List? _colors; final Color? _color; + /// Returns a [Color] or the first [Color] in the [List] of [Color]s. Color get color => _color != null ? _color! : _colors?.isNotEmpty ?? false @@ -33,11 +40,20 @@ class MultiColor { message: '_color is not defined or _colors is empty.', ); + /// Returns the [List] of [Color]s. + /// If the [List] is empty or if it is a single [MultiColor], it will return + /// an empty [List]. List get colors => _colors ?? []; + /// Returns `true` if the [MultiColor] is a [List] of [Color]s that is not + /// empty with a length greater than 1. bool get isGradient => (_colors?.length ?? 0) > 1; + + /// Returns `true` if the [MultiColor] is a [Color] or a [List] of [Color]s + /// that is not empty with a length greater than 1. bool get isColor => _color != null || isGradient; + /// Lerps between two [MultiColor]s. static MultiColor? lerp(MultiColor? a, MultiColor? b, double t) { if (a == null && b == null) { return null; diff --git a/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart b/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart index ba23b89b..2c6e248e 100644 --- a/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart +++ b/packages/wyatt_ui_components/lib/src/core/utils/text_wrapper.dart @@ -17,9 +17,12 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; +/// {@template text_wrapper} /// Wraps [String] and [TextStyle] into one object that can be /// a [Text] or a [RichText]. +/// {@endtemplate} class TextWrapper { + /// {@macro text_wrapper} const TextWrapper( this.data, { this.style, @@ -32,6 +35,7 @@ class TextWrapper { this.selectionColor, }); + /// Creates a [TextWrapper] from a [Text] widget. const TextWrapper.text(this.data) : style = null, gradientColors = null, diff --git a/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart b/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart index abefa83f..97fe94a0 100644 --- a/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart +++ b/packages/wyatt_ui_components/lib/src/core/utils/theme_helper.dart @@ -28,7 +28,6 @@ abstract class ThemeHelper { /// determines if a style element is valid. /// [combine]: A function that combines two [P] type objects to create /// a new object. - static T? getThemeElement( List? styles, { required T? Function(P?)? transform, diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/component.dart b/packages/wyatt_ui_components/lib/src/domain/entities/component.dart index e7f984f1..9cd334b5 100644 --- a/packages/wyatt_ui_components/lib/src/domain/entities/component.dart +++ b/packages/wyatt_ui_components/lib/src/domain/entities/component.dart @@ -17,6 +17,9 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/src/core/utils/theme_resolver.dart'; +/// {@template component} +/// Base class for all components. +/// {@endtemplate} abstract class Component extends StatelessWidget { const Component({this.themeResolver, super.key}); diff --git a/packages/wyatt_ui_components/lib/src/domain/entities/theme_style.dart b/packages/wyatt_ui_components/lib/src/domain/entities/theme_style.dart index a0a69ffb..89db71e2 100644 --- a/packages/wyatt_ui_components/lib/src/domain/entities/theme_style.dart +++ b/packages/wyatt_ui_components/lib/src/domain/entities/theme_style.dart @@ -14,7 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// {@template theme_style} +/// Base class for all theme styles. +/// {@endtemplate} abstract class ThemeStyle { + /// {@macro theme_style} const ThemeStyle(); /// Merges non-null `other` attributes in `this` and returns a copy. diff --git a/packages/wyatt_ui_components/lib/src/features/component_theme.dart b/packages/wyatt_ui_components/lib/src/features/component_theme.dart index 0ed44487..c7dc79d3 100644 --- a/packages/wyatt_ui_components/lib/src/features/component_theme.dart +++ b/packages/wyatt_ui_components/lib/src/features/component_theme.dart @@ -17,7 +17,12 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/src/features/features.dart'; +/// {@template component_theme} +/// A [ComponentTheme] widget that provides a [ComponentThemeData] to its +/// descendants. +/// {@endtemplate} class ComponentTheme extends StatelessWidget { + /// {@macro component_theme} const ComponentTheme({ required this.child, required this.componentThemeWidget, @@ -26,6 +31,9 @@ class ComponentTheme extends StatelessWidget { final Widget child; final ComponentThemeData componentThemeWidget; + /// Returns the [ComponentThemeData] of the closest ancestor [ComponentTheme] + /// widget. If there is no ancestor [ComponentTheme] widget, it throws an + /// assertion error. static ComponentThemeData of(BuildContext context) { final _InheritedComponentTheme? inheritedThemeComponent = context.dependOnInheritedWidgetOfExactType<_InheritedComponentTheme>(); @@ -37,6 +45,15 @@ class ComponentTheme extends StatelessWidget { return inheritedThemeComponent!.themeWidget.componentThemeWidget; } + /// Returns the [ComponentThemeData] of the closest ancestor [ComponentTheme] + /// widget. If there is no ancestor [ComponentTheme] widget, it returns null. + static ComponentThemeData? maybeOf(BuildContext context) { + final _InheritedComponentTheme? inheritedThemeComponent = + context.dependOnInheritedWidgetOfExactType<_InheritedComponentTheme>(); + + return inheritedThemeComponent?.themeWidget.componentThemeWidget; + } + @override Widget build(BuildContext context) => _InheritedComponentTheme( this, diff --git a/packages/wyatt_ui_components/lib/src/features/component_theme_data.dart b/packages/wyatt_ui_components/lib/src/features/component_theme_data.dart index aaff531d..c08e2502 100644 --- a/packages/wyatt_ui_components/lib/src/features/component_theme_data.dart +++ b/packages/wyatt_ui_components/lib/src/features/component_theme_data.dart @@ -18,6 +18,9 @@ import 'package:copy_with_extension/copy_with_extension.dart'; import 'package:wyatt_ui_components/src/domain/entities/entities.dart'; part 'component_theme_data.g.dart'; +/// {@template component_theme_data} +/// A class that holds all the components that are used in the app. +/// {@endtemplate} @CopyWith() class ComponentThemeData { factory ComponentThemeData({ diff --git a/packages/wyatt_ui_components/lib/wyatt_ui_components.dart b/packages/wyatt_ui_components/lib/wyatt_ui_components.dart index 3f16c3b1..e8cce321 100644 --- a/packages/wyatt_ui_components/lib/wyatt_ui_components.dart +++ b/packages/wyatt_ui_components/lib/wyatt_ui_components.dart @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// Wyatt Ui Components +/// Wyatt UI Components library wyatt_ui_components; export 'src/src.dart'; diff --git a/packages/wyatt_ui_components/pubspec.yaml b/packages/wyatt_ui_components/pubspec.yaml index 81f439f9..eecf6f81 100644 --- a/packages/wyatt_ui_components/pubspec.yaml +++ b/packages/wyatt_ui_components/pubspec.yaml @@ -1,9 +1,9 @@ name: wyatt_ui_components -description: Primary ui components +description: Components that can be implemented in any application with copy constructor. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_components version: 0.0.1 -publish_to: none +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: sdk: ">=2.17.0 <3.0.0" @@ -12,9 +12,8 @@ dependencies: flutter: { sdk: flutter } copy_with_extension: ^5.0.0 wyatt_component_copy_with_extension: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_component_copy_with_extension + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^1.0.0 dev_dependencies: flutter_test: { sdk: flutter } @@ -25,6 +24,5 @@ dev_dependencies: build_runner: ^2.3.3 copy_with_extension_gen: ^5.0.0 wyatt_component_copy_with_gen: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_component_copy_with_gen + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^1.0.0 diff --git a/packages/wyatt_ui_kit/.gitignore b/packages/wyatt_ui_kit/.gitignore deleted file mode 100644 index 3cceda55..00000000 --- a/packages/wyatt_ui_kit/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ - -# Avoid committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_ui_kit/.gitignore b/packages/wyatt_ui_kit/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_ui_kit/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_ui_kit/.pubignore b/packages/wyatt_ui_kit/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_ui_kit/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_ui_kit/AUTHORS b/packages/wyatt_ui_kit/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_ui_kit/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_ui_kit/LICENSE b/packages/wyatt_ui_kit/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_ui_kit/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_ui_kit/README.md b/packages/wyatt_ui_kit/README.md index 8ee9ac74..909c37ea 100644 --- a/packages/wyatt_ui_kit/README.md +++ b/packages/wyatt_ui_kit/README.md @@ -16,54 +16,60 @@ * along with this program. If not, see . --> -# Flutter - Wyatt Ui Kit +# Wyatt UI Kit

Style: Wyatt Analysis SDK: Flutter

-UIKit and Design System used in Wyatt Studio. - -## Theme negotiation - -When building a component, most of its attributes can be 'null'. -The `build()` method then starts to negotiate the theme in the tree to obtain the most consistent style possible. - -Explanation: - -When you build a component `Button({double? radius})`. -You have several possibilities: -1) Pass the "radius" into the constructor, `Button(radius: 12)`. -2) Set up a theme extension `ButtonThemeExtension(radius: 15)`. -3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the flutter theme. - -If this negotiation phase fails, then: -- If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen. -- If not, the style is simply not applied. - -If, for example, you don't use option 1, then the radius will be 15. If you use neither option 1 nor option 2 then the radius will be 4 as this is the [official Material Design value](https://m2.material.io/design/shape/about-shape.html#shape-customization-tool). - -## Features - -TODO: List what your package can do. Maybe include images, gifs, or videos. - -## Getting started - -TODO: List prerequisites and provide or point to information on how to -start using the package. +UIKit and Design System used in Wyatt Studio. This is a implementation of the components defined in [Wyatt UI Components](https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_components) package. ## Usage -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. +The UIKit provides `WyattComponentThemeData` class that contains all the components used in Wyatt Studio. You can use it in your app by calling `WyattComponentTheme` widget and give your app as child. For example : + +This component theme is to be used with Wyatt UI Components. It provides a default theme for all the components defined in Wyatt UI Components package. ```dart -const like = 'sample'; +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) => ComponentTheme( + // It is here that you can override the default theme ! + componentThemeWidget: WyattComponentThemeData(), + child: MaterialApp( + title: 'Wyatt Ui Layout Example', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const .., + ), + ); +} ``` -## Additional information +## Development -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +> Common to this, and Wyatt UI Components packages. + +Add a new component : + +**Wyatt UI Components side** + + 1. Create a new file in `lib/src/domain/entities` folder. + 2. Add your component class. + 3. Add your component class to `ComponentThemeData` abstract class. + 4. Run `flutter pub run build_runner build` to generate your component proxy properties. + +**Wyatt UI Kit side** + 1. Create a new file in `lib/src/components` folder. + 2. Add your component class, styles, (and logic if needed) + 3. Run `flutter pub run build_runner build` to generate your component copy with method. + 4. Add a theme extension to your component class in `lib/src/domain/` + 5. Add your component class `wyattComponentThemeData` static property in `lib/src/features/wyatt_component_theme_data.dart` diff --git a/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart b/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart index 8b608cb0..5750eb26 100644 --- a/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart +++ b/packages/wyatt_ui_kit/lib/src/components/bars/widgets/navigation_item.dart @@ -38,7 +38,7 @@ class NavigationItem extends StatelessWidget { context .themeExtension() ?.selectedIndicatorHeight, - // TODO: move default value + // TODO(wyatt): move default value 5, ], valueValidator: (value) => value != null, @@ -49,7 +49,7 @@ class NavigationItem extends StatelessWidget { context .themeExtension() ?.selectedIndicatorWidth, - // TODO: move default value + // TODO(wyatt): move default value 70, ], valueValidator: (value) => value != null, @@ -72,16 +72,17 @@ class NavigationItem extends StatelessWidget { ConstrainedBox( constraints: BoxConstraints( minWidth: ThemeHelper.getThemeElement( - [ - context - .themeExtension() - ?.selectedIndicatorWidth, - // TODO: move default value - 70, - ], - valueValidator: (value) => value != null, - transform: (value) => value, - ) ?? double.infinity, + [ + context + .themeExtension() + ?.selectedIndicatorWidth, + // TODO(wyatt): move default value + 70, + ], + valueValidator: (value) => value != null, + transform: (value) => value, + ) ?? + double.infinity, ), child: SizedBox( height: 50, diff --git a/packages/wyatt_ui_kit/pubspec.yaml b/packages/wyatt_ui_kit/pubspec.yaml index d34b1dbc..68082704 100644 --- a/packages/wyatt_ui_kit/pubspec.yaml +++ b/packages/wyatt_ui_kit/pubspec.yaml @@ -3,7 +3,7 @@ description: UIKit and Design System used in Wyatt Studio. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_kit version: 1.0.0 -publish_to: none +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: sdk: ">=2.19.0 <3.0.0" @@ -22,13 +22,11 @@ dependencies: name: wyatt_bloc_helper version: 2.0.0 wyatt_component_copy_with_extension: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_component_copy_with_extension + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^1.0.0 wyatt_ui_components: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_ui_components + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 dev_dependencies: build_runner: ^2.3.3 @@ -37,10 +35,5 @@ dev_dependencies: hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub version: ^2.4.1 wyatt_component_copy_with_gen: - git: - url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git - path: packages/wyatt_component_copy_with_gen - -# The following section is specific to Flutter. -flutter: - uses-material-design: true + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^1.0.0 diff --git a/packages/wyatt_ui_layout/.gitignore b/packages/wyatt_ui_layout/.gitignore deleted file mode 100644 index e38f9b0c..00000000 --- a/packages/wyatt_ui_layout/.gitignore +++ /dev/null @@ -1,133 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/* - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* -!.vscode/settings.json -!.vscode/extensions.json - -# Flutter repo-specific -/bin/cache/ -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds -.fvm/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -**/android/.idea/ -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/.last_build_id -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Coverage -coverage/ - -# Submodules -!pubspec.lock -packages/**/pubspec.lock - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to the above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/extensions.json -!.vscode/launch.json -!.idea/codeStyles/ -!.idea/dictionaries/ -!.idea/runConfigurations/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/packages/wyatt_ui_layout/.gitignore b/packages/wyatt_ui_layout/.gitignore new file mode 120000 index 00000000..6ef08f9d --- /dev/null +++ b/packages/wyatt_ui_layout/.gitignore @@ -0,0 +1 @@ +../../.gitignore \ No newline at end of file diff --git a/packages/wyatt_ui_layout/.pubignore b/packages/wyatt_ui_layout/.pubignore new file mode 120000 index 00000000..52b2f28d --- /dev/null +++ b/packages/wyatt_ui_layout/.pubignore @@ -0,0 +1 @@ +../../.pubignore \ No newline at end of file diff --git a/packages/wyatt_ui_layout/AUTHORS b/packages/wyatt_ui_layout/AUTHORS deleted file mode 100644 index f9506138..00000000 --- a/packages/wyatt_ui_layout/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to this project. Names should be added to the list like so: -# -# Name/Organization - -Wyatt Group S.A.S -Hugo Pointcheval -Malo Léon \ No newline at end of file diff --git a/packages/wyatt_ui_layout/AUTHORS b/packages/wyatt_ui_layout/AUTHORS new file mode 120000 index 00000000..f04b7e8a --- /dev/null +++ b/packages/wyatt_ui_layout/AUTHORS @@ -0,0 +1 @@ +../../AUTHORS \ No newline at end of file diff --git a/packages/wyatt_ui_layout/LICENSE b/packages/wyatt_ui_layout/LICENSE deleted file mode 100644 index e72bfdda..00000000 --- a/packages/wyatt_ui_layout/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/packages/wyatt_ui_layout/LICENSE b/packages/wyatt_ui_layout/LICENSE new file mode 120000 index 00000000..30cff740 --- /dev/null +++ b/packages/wyatt_ui_layout/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/packages/wyatt_ui_layout/README.md b/packages/wyatt_ui_layout/README.md index e8d1656d..af77bf5f 100644 --- a/packages/wyatt_ui_layout/README.md +++ b/packages/wyatt_ui_layout/README.md @@ -7,7 +7,7 @@ * the Free Software Foundation, either version 3 of the License, or * any later version. - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -16,12 +16,10 @@ * along with this program. If not, see . --> -# Flutter - Wyatt Ui Layout +# Wyatt UI Layout

- - Style: Wyatt Analysis - + Style: Wyatt Analysis SDK: Flutter

@@ -31,19 +29,19 @@ Wyatt UI Layout is a Flutter package that provides pre-built layouts to make the Structural layouts are used to structure the GUI, and there are currently four layouts provided by this package: -- #### TopAppBarLayout +* #### TopAppBarLayout This layout is used to create a GUI with a classic app bar and a body. -- #### TopNavigationBarLayout +* #### TopNavigationBarLayout This layout is used to create a GUI with an app bar that includes navigation options and a body. -- #### BottomNavigationBarLayout +* #### BottomNavigationBarLayout This layout is used to create a GUI with a bottom bar that includes navigation options and a body. -- #### FrameLayout +* #### FrameLayout This layout is used to create a GUI that includes a classic app bar, a bottom navigation bar, and a body. @@ -51,19 +49,6 @@ This layout is used to create a GUI that includes a classic app bar, a bottom na Content layouts are used to display dynamic data and content within the GUI. Currently, there is only one content layout provided by this package: -- #### GridLayout +* #### GridLayout This layout is used to display data and content in a grid layout. - -### Installation - -To use Wyatt UI Layout in your Flutter project, add the following dependency to your pubspec.yaml file: - -```yaml -wyatt_ui_layout: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_ui_layout -``` - -That's it! You're now ready to use Wyatt UI Layout in your project. diff --git a/packages/wyatt_ui_layout/analysis_options.yaml b/packages/wyatt_ui_layout/analysis_options.yaml index f8bb612a..e66159fc 100644 --- a/packages/wyatt_ui_layout/analysis_options.yaml +++ b/packages/wyatt_ui_layout/analysis_options.yaml @@ -1,19 +1,2 @@ -# Copyright (C) 2022 WYATT GROUP -# Please see the AUTHORS file for details. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - include: package:wyatt_analysis/analysis_options.flutter.yaml diff --git a/packages/wyatt_ui_layout/lib/src/presentation/layouts/content_layouts/grid_layout.dart b/packages/wyatt_ui_layout/lib/src/presentation/layouts/content_layouts/grid_layout.dart index c06014c1..04c9a7a0 100644 --- a/packages/wyatt_ui_layout/lib/src/presentation/layouts/content_layouts/grid_layout.dart +++ b/packages/wyatt_ui_layout/lib/src/presentation/layouts/content_layouts/grid_layout.dart @@ -18,7 +18,12 @@ import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; +/// {@template grid_layout} +/// A concrete implementation of the [ContentLayout] abstract class for a layout +/// which defines a layout structure with a grid layout. +/// {@endtemplate} class GridLayout extends ContentLayout { + /// {@macro grid_layout} const GridLayout({ required this.children, this.verticalGap = 30, @@ -26,8 +31,13 @@ class GridLayout extends ContentLayout { super.key, }); + /// The children of the layout. final List children; + + /// The vertical gap between the children. final double verticalGap; + + /// The horizontal gap between the children. final double horizontalGap; @override diff --git a/packages/wyatt_ui_layout/lib/src/presentation/layouts/layout.dart b/packages/wyatt_ui_layout/lib/src/presentation/layouts/layout.dart index 41f839a8..28068913 100644 --- a/packages/wyatt_ui_layout/lib/src/presentation/layouts/layout.dart +++ b/packages/wyatt_ui_layout/lib/src/presentation/layouts/layout.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022 WYATT GROUP +// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify @@ -14,28 +14,35 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// This file contains the [Layout] abstract class, which provides a base -/// for creating custom layout widgets in Flutter. -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +/// {@template layout} /// An abstract class that provides a base for creating custom layout widgets. /// /// This class can be used as a base for creating custom layout widgets in /// Flutter. It extends the [StatelessWidget] class and adds support for /// providing a custom key. Custom layout widgets that extend this class should /// override the [build] method to define the layout. +/// {@endtemplate} abstract class Layout extends StatelessWidget { - /// Creates a new [Layout] instance. - /// - /// [key] is an optional parameter that can be used to provide a custom key - /// for the widget. + /// {@macro layout} const Layout({super.key}); } +/// {@template structural_layout} +/// An abstract class that provides a base for creating custom structural layout +/// widgets. +/// {@endtemplate} abstract class StructuralLayout extends Layout { + /// {@macro structural_layout} const StructuralLayout({super.key}); } +/// {@template content_layout} +/// An abstract class that provides a base for creating custom content layout +/// widgets. +/// {@endtemplate} abstract class ContentLayout extends Layout { + /// {@macro content_layout} const ContentLayout({super.key}); } diff --git a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/bottom_navigation_bar_layout.dart b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/bottom_navigation_bar_layout.dart index 4ef676de..d8755e92 100644 --- a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/bottom_navigation_bar_layout.dart +++ b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/bottom_navigation_bar_layout.dart @@ -14,34 +14,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// This file contains the concrete class [BottomNavigationBarLayout]. -/// -/// The [BottomNavigationBarLayout] class is a concrete implementation of the -/// [Layout] abstract class, which defines a layout structure with a bottom -/// navigation bar component. -/// -/// [BottomNavigationBarLayout] includes an optional -/// [BottomNavigationBarLayout.custom] -/// function for customizing the bottom navigation bar component. import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; -/// A concrete implementation of the [Layout] abstract class for a layout with -/// a bottom navigation bar component. +/// {@template bottom_navigation_bar_layout} +/// A concrete implementation of the [Layout] abstract class for a layout which +/// defines a layout structure with a bottom navigation bar component. +/// {@endtemplate} class BottomNavigationBarLayout extends StructuralLayout { - /// Creates a [BottomNavigationBarLayout] instance. - /// - /// [body] represents the main content of the layout. - /// [custom] is an optional function that can be used to customize - /// the bottom navigation bar component. + /// {@macro bottom_navigation_bar_layout} const BottomNavigationBarLayout({ required this.body, this.custom, super.key, }); + /// The main content of the layout. final Widget? body; + + /// An optional function that can be used to customize the bottom navigation + /// bar component. final BottomNavigationBarComponent? Function(BottomNavigationBarComponent?)? custom; diff --git a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/frame_layout.dart b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/frame_layout.dart index 79e28793..144ef867 100644 --- a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/frame_layout.dart +++ b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/frame_layout.dart @@ -18,6 +18,7 @@ import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; +/// {@template frame_layout} /// A layout that contains a top app bar, a body and a bottom navigation bar. /// /// This layout consists of a [TopAppBarComponent] at the top of the screen, @@ -25,15 +26,9 @@ import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; /// You can customize the app bar and the bottom navigation bar by passing /// a [customAppBar] and a [customBottomNavBar] functions that take /// the corresponding components and return the customized ones. +/// {@endtemplate} class FrameLayout extends StructuralLayout { - /// Creates a [FrameLayout] instance. - /// - /// [body] represents the main content of the layout. - /// [customAppBar] is an optional function that can be used to customize - /// the top app bar component. - /// [customBottomNavBar] is an optional function that can be used to customize - /// the bottom navigation bar component. - /// [height] represents the height of the top app bar. + /// {@macro frame_layout} const FrameLayout({ required this.body, this.customAppBar, @@ -42,10 +37,17 @@ class FrameLayout extends StructuralLayout { super.key, }); + /// An optional function that can be used to customize the top app bar final TopAppBarComponent? Function(TopAppBarComponent?)? customAppBar; + + /// An optional function that can be used to customize the bottom navigation final BottomNavigationBarComponent? Function(BottomNavigationBarComponent?)? customBottomNavBar; + + /// The main content of the layout. final Widget body; + + /// The height of the top app bar. final double height; @override diff --git a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/top_app_bar_layout.dart b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/top_app_bar_layout.dart index e69054bb..70f61b1e 100644 --- a/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/top_app_bar_layout.dart +++ b/packages/wyatt_ui_layout/lib/src/presentation/layouts/structural_layouts/top_app_bar_layout.dart @@ -14,16 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// This file contains the abstract class [TopBarLayout] and two concrete -/// classes [TopAppBarLayout] and [TopNavigationBarLayout]. -/// The [TopBarLayout] abstract class defines a layout structure with a top bar. -/// The [TopAppBarLayout] and [TopNavigationBarLayout] classes are concrete -/// implementations of the [TopBarLayout] class. - import 'package:flutter/material.dart'; import 'package:wyatt_ui_components/wyatt_ui_components.dart'; import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; +/// {@template top_bar_layout} /// An abstract class for creating layouts with a top bar component. /// /// This class provides a base for creating layouts that include a top bar @@ -34,14 +29,10 @@ import 'package:wyatt_ui_layout/src/presentation/layouts/layout.dart'; /// given [BuildContext]. /// /// [T] represents the type of the top bar component. +/// {@endtemplate} abstract class TopBarLayout extends StructuralLayout { - /// Creates a [TopBarLayout] instance. - /// - /// [body] represents the main content of the layout. - /// [custom] is an optional function that can be used to customize - /// the top bar component. - /// [height] represents the height of the top bar. + /// {@macro top_bar_layout} const TopBarLayout({ required this.body, this.custom, @@ -49,9 +40,15 @@ abstract class TopBarLayout super.key, }); + /// The main content of the layout. final Widget body; + /// An optional function that can be used to customize the top bar component. + /// The function takes the top bar component as an argument and returns + /// a customized top bar component. final T? Function(T?)? custom; + + /// The height of the top bar. final double height; /// Returns the top bar component for the given [BuildContext]. diff --git a/packages/wyatt_ui_layout/lib/wyatt_ui_layout.dart b/packages/wyatt_ui_layout/lib/wyatt_ui_layout.dart index 5ab915d4..ac5430dc 100644 --- a/packages/wyatt_ui_layout/lib/wyatt_ui_layout.dart +++ b/packages/wyatt_ui_layout/lib/wyatt_ui_layout.dart @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// Wyatt Ui Layout +/// Wyatt UI Layout library wyatt_ui_layout; export 'src/src.dart'; diff --git a/packages/wyatt_ui_layout/pubspec.yaml b/packages/wyatt_ui_layout/pubspec.yaml index 7c8703ed..aaaf1130 100644 --- a/packages/wyatt_ui_layout/pubspec.yaml +++ b/packages/wyatt_ui_layout/pubspec.yaml @@ -3,27 +3,22 @@ description: Main layouts to help you build your application views. repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_ui_layout version: 0.0.1 -publish_to: "none" +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub environment: sdk: ">=2.17.0 <3.0.0" dependencies: - flutter: - sdk: flutter + flutter: { sdk: flutter } gap: ^2.0.1 wyatt_ui_components: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - path: packages/wyatt_ui_components + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^0.0.1 dev_dependencies: - flutter_test: - sdk: flutter + flutter_test: { sdk: flutter } wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.4.1 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + version: ^2.4.1 diff --git a/scripts/clean_gitignore.sh b/scripts/clean_gitignore.sh new file mode 100755 index 00000000..74e5e289 --- /dev/null +++ b/scripts/clean_gitignore.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 WYATT GROUP +# Please see the AUTHORS file for details. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Script that iterates through each package in the packages directory and +# removes .gitignore, AUTHORS, and LICENSE files if they exist. + +# Current directory +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +# Path to the packages directory +PACKAGES_DIR="$DIR/../packages" + +# Iterate through each package in the packages directory +for package in "$PACKAGES_DIR"/*; do + # Remove .gitignore file if it exists + if [ -f "$package/.gitignore" ]; then + rm "$package/.gitignore" + fi + + # Remove .pubignore file if it exists + if [ -f "$package/.pubignore" ]; then + rm "$package/.pubignore" + fi + + # Remove AUTHORS file if it exists + if [ -f "$package/AUTHORS" ]; then + rm "$package/AUTHORS" + fi + + # Remove LICENSE file if it exists + if [ -f "$package/LICENSE" ]; then + rm "$package/LICENSE" + fi +done diff --git a/scripts/symbolic_links.sh b/scripts/symbolic_links.sh new file mode 100755 index 00000000..1d2b6e59 --- /dev/null +++ b/scripts/symbolic_links.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 WYATT GROUP +# Please see the AUTHORS file for details. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Script that iterates through each package in the packages directory and +# creates a symbolic link to the main .gitignore file, AUTHORS, and LICENSE +# files if they do not already exist. + +# Current directory +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +# Path to the packages directory +PACKAGES_DIR="$DIR/../packages" + +# Iterate through each package in the packages directory +for package in "$PACKAGES_DIR"/*; do + # Go to the package directory + cd "$package" + + # Create symbolic link to the main .gitignore file if it does not already + # exist + if [ ! -f .gitignore ]; then + ln -s ../../.gitignore .gitignore + fi + + # Create symbolic link to the main .pubignore file if it does not already + # exist + if [ ! -f .pubignore ]; then + ln -s ../../.pubignore .pubignore + fi + + # Create symbolic link to the main AUTHORS file if it does not already + # exist + + if [ ! -f AUTHORS ]; then + ln -s ../../AUTHORS AUTHORS + fi + + # Create symbolic link to the main LICENSE file if it does not already + # exist + if [ ! -f LICENSE ]; then + ln -s ../../LICENSE LICENSE + fi +done