diff --git a/.github/workflows/localization.yml b/.github/workflows/localization.yml index 6976e40e1..7107bf766 100644 --- a/.github/workflows/localization.yml +++ b/.github/workflows/localization.yml @@ -25,7 +25,7 @@ jobs: channel: "stable" flutter-version: "3.10.2" cache: true - + - name: Setup Config run: | git config --global user.name 'mobile-apps-deriv' @@ -38,11 +38,11 @@ jobs: ./l10n.sh env: GITHUB_TOKEN: ${{ secrets.PAT }} - - name: Create Pull Request. uses: peter-evans/create-pull-request@76c6f5c20e2111bfee3cd30fae52a25e410f5efc with: token: ${{ secrets.PAT }} title: "refactor(deriv_localizations): Crowdin Localization Generated" + branch: create-pull-request/localisation base: master diff --git a/.github/workflows/version.yaml b/.github/workflows/version.yaml index 7a764da3c..37d18284a 100644 --- a/.github/workflows/version.yaml +++ b/.github/workflows/version.yaml @@ -77,13 +77,6 @@ jobs: run: bash readme.sh working-directory: ./scripts - - name: Create Pull Request on updated changelog and pubspec file. - uses: peter-evans/create-pull-request@76c6f5c20e2111bfee3cd30fae52a25e410f5efc - with: - token: ${{ secrets.PAT }} - title: "chore(version): bump version and update changelog" - base: master - - name: Send Slack Notification uses: ./.github/actions/send_slack_notifications if: ${{ contains(steps.push-tag.outputs.PUSH_OUTPUT, 'Packages updated') }} @@ -91,3 +84,10 @@ jobs: SLACK_WEBHOOK_PACKAGE_UPDATE: ${{ secrets.SLACK_WEBHOOK_PACKAGE_UPDATE }} PR_TITLE: ${{ github.event.pull_request.title }} TAGS: ${{ steps.new-tags.outputs.NEW_TAGS }} + + - name: Create Pull Request on updated changelog and pubspec file. + uses: peter-evans/create-pull-request@76c6f5c20e2111bfee3cd30fae52a25e410f5efc + with: + token: ${{ secrets.PAT }} + title: "chore(version): bump version and update changelog" + base: master diff --git a/CHANGELOG.md b/CHANGELOG.md index 387a99d3a..3df7b664a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,208 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-07-17 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_auth` - `v6.7.17`](#deriv_auth---v6717) + - [`deriv_passkeys` - `v0.0.3+5`](#deriv_passkeys---v0035) + +--- + +#### `deriv_auth` - `v6.7.17` + + - **REFACTOR**(version): updated the version of flutter deriv api ([#694](https://github.com/regentmarkets/flutter-deriv-packages/issues/694)). ([eac7e8cb](https://github.com/regentmarkets/flutter-deriv-packages/commit/eac7e8cba4e9310d30296e07a47731f08d4d7342)) + +#### `deriv_passkeys` - `v0.0.3+5` + + - **REFACTOR**(version): updated the version of flutter deriv api ([#694](https://github.com/regentmarkets/flutter-deriv-packages/issues/694)). ([eac7e8cb](https://github.com/regentmarkets/flutter-deriv-packages/commit/eac7e8cba4e9310d30296e07a47731f08d4d7342)) + + +## 2024-07-16 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_passkeys` - `v0.0.3+4`](#deriv_passkeys---v0034) + - [`deriv_auth` - `v6.7.16`](#deriv_auth---v6716) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `deriv_auth` - `v6.7.16` + +--- + +#### `deriv_passkeys` - `v0.0.3+4` + + - **FIX**(deriv_passkeys): fix some missing keys in passkey login page ([#692](https://github.com/regentmarkets/flutter-deriv-packages/issues/692)). ([d944a1c3](https://github.com/regentmarkets/flutter-deriv-packages/commit/d944a1c37f127f35143d9920532f76bc3487ebd4)) + + +## 2024-07-16 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_auth` - `v6.7.15`](#deriv_auth---v6715) + - [`deriv_language_selector` - `v0.0.2+9`](#deriv_language_selector---v0029) + - [`deriv_mobile_chart_wrapper` - `v0.0.2+3`](#deriv_mobile_chart_wrapper---v0023) + - [`deriv_passkeys` - `v0.0.3+3`](#deriv_passkeys---v0033) + - [`deriv_ui` - `v0.0.8+1`](#deriv_ui---v0081) + - [`deriv_widgetbook` - `v0.0.2+11`](#deriv_widgetbook---v00211) + - [`update_checker` - `v1.5.1`](#update_checker---v151) + +--- + +#### `deriv_auth` - `v6.7.15` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `deriv_language_selector` - `v0.0.2+9` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `deriv_mobile_chart_wrapper` - `v0.0.2+3` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `deriv_passkeys` - `v0.0.3+3` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `deriv_ui` - `v0.0.8+1` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `deriv_widgetbook` - `v0.0.2+11` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +#### `update_checker` - `v1.5.1` + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + + +## 2024-07-15 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_ui` - `v0.0.8`](#deriv_ui---v008) + - [`update_checker` - `v1.5.0`](#update_checker---v150) + - [`deriv_auth` - `v6.7.14`](#deriv_auth---v6714) + - [`deriv_mobile_chart_wrapper` - `v0.0.2+2`](#deriv_mobile_chart_wrapper---v0022) + - [`deriv_passkeys` - `v0.0.3+2`](#deriv_passkeys---v0032) + - [`deriv_widgetbook` - `v0.0.2+10`](#deriv_widgetbook---v00210) + - [`deriv_language_selector` - `v0.0.2+8`](#deriv_language_selector---v0028) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `deriv_auth` - `v6.7.14` + - `deriv_mobile_chart_wrapper` - `v0.0.2+2` + - `deriv_passkeys` - `v0.0.3+2` + - `deriv_widgetbook` - `v0.0.2+10` + - `deriv_language_selector` - `v0.0.2+8` + +--- + +#### `deriv_ui` - `v0.0.8` + + - **FEAT**(deriv_ui): [DERG 2450] Added Timeline Widget to Deriv UI ([#631](https://github.com/regentmarkets/flutter-deriv-packages/issues/631)). ([e34d78b3](https://github.com/regentmarkets/flutter-deriv-packages/commit/e34d78b303358cb5f91abab14a2a042ce3650b0f)) + +#### `update_checker` - `v1.5.0` + + - **FEAT**(deriv_ui): [DERG 2450] Added Timeline Widget to Deriv UI ([#631](https://github.com/regentmarkets/flutter-deriv-packages/issues/631)). ([e34d78b3](https://github.com/regentmarkets/flutter-deriv-packages/commit/e34d78b303358cb5f91abab14a2a042ce3650b0f)) + + +## 2024-07-11 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_passkeys` - `v0.0.3+1`](#deriv_passkeys---v0031) + - [`deriv_auth` - `v6.7.13`](#deriv_auth---v6713) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `deriv_auth` - `v6.7.13` + +--- + +#### `deriv_passkeys` - `v0.0.3+1` + + - **FIX**(deriv_passkeys): add keys to passkey login page ([#676](https://github.com/regentmarkets/flutter-deriv-packages/issues/676)). ([aa84a46d](https://github.com/regentmarkets/flutter-deriv-packages/commit/aa84a46dfb9cd22a335276c1ae0063ffee7852ef)) + + +## 2024-07-10 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`deriv_passkeys` - `v0.0.3`](#deriv_passkeys---v003) + - [`deriv_auth` - `v6.7.12`](#deriv_auth---v6712) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `deriv_auth` - `v6.7.12` + +--- + +#### `deriv_passkeys` - `v0.0.3` + + - **FEAT**(deriv_passkeys): [P2PS-3072] add keys to deriv passkey package effortless passkeys login page ([#677](https://github.com/regentmarkets/flutter-deriv-packages/issues/677)). ([39472704](https://github.com/regentmarkets/flutter-deriv-packages/commit/39472704a3d264bc5f64ba2ae75e29134f890590)) + + ## 2024-07-04 ### Changes @@ -16,6 +218,7 @@ Packages with breaking changes: Packages with other changes: - [`deriv_mobile_chart_wrapper` - `v0.0.2+1`](#deriv_mobile_chart_wrapper---v0021) + - deriv_auth-v6.7.11 --- diff --git a/README.md b/README.md index c466af883..829032b11 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,14 @@ cp $HOME/Downloads/commit-msg $HOME/.git/hooks/commit-msg \ ## Using the packages -Each package has been released as git tag with convention as **packageName-vVersionNumber**`(Example: deriv_auth-v6.7.10)`. To use the package, add the following to your pubspec.yaml file: +Each package has been released as git tag with convention as **packageName-vVersionNumber**`(Example: deriv_auth-v6.7.17)`. To use the package, add the following to your pubspec.yaml file: ```yaml deriv_ui: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 #your prefered version + ref: deriv_ui-v0.0.8+1 #your prefered version ``` ## Packages @@ -30,7 +30,7 @@ deriv_ui: | Name | Description | Version | | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | [analytics](./packages/analytics) | Used to collect and send analytical information to 'Firebase' and 'Segment'. | [v2.1.0](./packages/analytics/CHANGELOG.md) | -| [deriv_auth](./packages/deriv_auth) | A Dart package that provides Authentication logic for Deriv applications. | [v6.7.10 ](./packages/deriv_auth/CHANGELOG.md) | +| [deriv_auth](./packages/deriv_auth) | A Dart package that provides Authentication logic for Deriv applications. | [v6.7.17 ](./packages/deriv_auth/CHANGELOG.md) | | [deriv_banner](./packages/deriv_banner) | A widget to show banner in apps. | [v0.0.1+1](./packages/deriv_banner/CHANGELOG.md) | | [deriv_bloc_manager](./packages/deriv_bloc_manager) | Provides some tools to manage blocs. | [v0.0.1](./packages/deriv_bloc_manager/CHANGELOG.md) | | [deriv_datadog](./packages/deriv_datadog) | A package that helps you monitor the performance and user interactions of your Flutter app by sending data to Datadog. | [v0.0.1](./packages/deriv_datadog/CHANGELOG.md) | @@ -41,20 +41,20 @@ deriv_ui: | [deriv_http_client](./packages/deriv_http_client) | A package that provides a wrapper for http package. | [v2.0.0](./packages/deriv_http_client/CHANGELOG.md) | | [deriv_lint](./packages/deriv_lint) | A Dart package that provides lint rules for Dart and Flutter. | [v1.0.0](./packages/deriv_lint/CHANGELOG.md) | | [deriv_live_chat](./packages/deriv_live_chat) | A plugin for live chat SDK support to dart. | [v0.0.1+2](./packages/deriv_live_chat/CHANGELOG.md) | -| [deriv_language_selector](./packages/deriv_language_selector) | A package to handle language change of the app. | [v0.0.2+7](./packages/deriv_language_selector/CHANGELOG.md) | +| [deriv_language_selector](./packages/deriv_language_selector) | A package to handle language change of the app. | [v0.0.2+9](./packages/deriv_language_selector/CHANGELOG.md) | | [deriv_localizations](./packages/deriv_localizations) | A Package that contains the localization arb(coming from Crowdin) and dart generated files for flutter_deriv_packages. | [v1.5.1](./packages/deriv_localizations/CHANGELOG.md) | | [deriv_numpad](./packages/deriv_numpad) | Number Pad Widget for number input. | [v1.1.5](./packages/deriv_numpad/CHANGELOG.md) | | [deriv_rudderstack](./packages/deriv_rudderstack) | A plugin that add RudderStack SDK support to Flutter. | [v1.1.0](./packages/deriv_rudderstack/CHANGELOG.md) | | [deriv_store_launcher](./packages/deriv_store_launcher) | A plugin to launch app stores base on platform and manufacturer. | [v0.0.1+1](./packages/deriv_store_launcher/CHANGELOG.md) | | [deriv_technical_analysis](./packages/deriv_technical_analysis) | A Dart package for Technical Analysis. | [v0.0.1](./packages/deriv_technical_analysis/CHANGELOG.md) | | [deriv_theme](./packages/deriv_theme) | A package that contains the theme used by Deriv products. | [v2.4.0](./packages/deriv_theme/CHANGELOG.md) | -| [deriv_ui](./packages/deriv_ui) | A package that contains the UI components used by Deriv products. | [v0.0.7+9](./packages/deriv_ui/CHANGELOG.md) | +| [deriv_ui](./packages/deriv_ui) | A package that contains the UI components used by Deriv products. | [v0.0.8+1](./packages/deriv_ui/CHANGELOG.md) | | [deriv_utilities](./packages/deriv_utilities) | A package that contains the utilities including helper functions, mixins, and extensions. | [v1.0.0](./packages/deriv_utilities/CHANGELOG.md) | | [deriv_websocket](./packages/deriv_web_socket_client) | A package that provides a easy to use websocket client. | [v1.0.1](./packages/deriv_web_socket_client/CHANGELOG.md) | | [deriv_web_view](./packages/deriv_web_view) | Deriv web view package. | [v0.2.2+3](./packages/deriv_web_view/CHANGELOG.md) | -| [deriv_widgetbook](./packages/deriv_widgetbook) | Storybook for Deriv UI Widgets and Components | [v0.0.2+9](./packages/deriv_widgetbook/CHANGELOG.md) | +| [deriv_widgetbook](./packages/deriv_widgetbook) | Storybook for Deriv UI Widgets and Components | [v0.0.2+11](./packages/deriv_widgetbook/CHANGELOG.md) | | [form_builder](./packages/form_builder) | A simpler and cleaner way to create, validate and submit forms. | [v1.0.0+1](./packages/form_builder/CHANGELOG.md) | -| [update_checker](./packages/update_checker) | Check and retrieve update information from the server for the given package. | [v1.4.0](./packages/update_checker/CHANGELOG.md) | +| [update_checker](./packages/update_checker) | Check and retrieve update information from the server for the given package. | [v1.5.1](./packages/update_checker/CHANGELOG.md) | | [deriv_feature_flag](./packages/deriv_feature_flag) | A package to provide feature flag functionality for apps. | [v0.1.1](./packages/deriv_feature_flag/CHANGELOG.md) | ## Environment Setup diff --git a/packages/deriv_auth/CHANGELOG.md b/packages/deriv_auth/CHANGELOG.md index 5d864bd33..0560ff53b 100644 --- a/packages/deriv_auth/CHANGELOG.md +++ b/packages/deriv_auth/CHANGELOG.md @@ -1,3 +1,27 @@ +## 6.7.17 + + - **REFACTOR**(version): updated the version of flutter deriv api ([#694](https://github.com/regentmarkets/flutter-deriv-packages/issues/694)). ([eac7e8cb](https://github.com/regentmarkets/flutter-deriv-packages/commit/eac7e8cba4e9310d30296e07a47731f08d4d7342)) + +## 6.7.16 + + - Update a dependency to the latest release. + +## 6.7.15 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 6.7.14 + + - Update a dependency to the latest release. + +## 6.7.13 + + - Update a dependency to the latest release. + +## 6.7.12 + + - Update a dependency to the latest release. + ## 6.7.10 - **FIX**(deriv_auth): minor change in readme file ([#669](https://github.com/regentmarkets/flutter-deriv-packages/issues/669)). ([b29d222c](https://github.com/regentmarkets/flutter-deriv-packages/commit/b29d222ce219d0664e3cafb6c302cd1041749905)) diff --git a/packages/deriv_auth/example/pubspec.yaml b/packages/deriv_auth/example/pubspec.yaml index a2b58d10e..24fd8a335 100644 --- a/packages/deriv_auth/example/pubspec.yaml +++ b/packages/deriv_auth/example/pubspec.yaml @@ -23,7 +23,7 @@ dependency_overrides: flutter_deriv_api: git: url: git@github.com:deriv-com/flutter-deriv-api.git - ref: v1.0.0 + ref: v1.1.0 dev_dependencies: flutter_test: diff --git a/packages/deriv_auth/lib/features/auth/services/deriv_auth_service.dart b/packages/deriv_auth/lib/features/auth/services/deriv_auth_service.dart index fe64da79c..5730982a0 100644 --- a/packages/deriv_auth/lib/features/auth/services/deriv_auth_service.dart +++ b/packages/deriv_auth/lib/features/auth/services/deriv_auth_service.dart @@ -86,20 +86,23 @@ class DerivAuthService extends BaseAuthService { responseAuthorizeEntity!.copyWith( signupProvider: signupProvider, refreshToken: refreshToken, - accountList: responseAuthorizeEntity.accountList - ?.map( - (AccountListItem accountListItem) => accountListItem.copyWith( - token: accounts - .where( - (AccountModel element) => - element.accountId == accountListItem.loginid, - ) - .firstOrNull - ?.token ?? - token, - ), - ) - .toList(), + accountList: responseAuthorizeEntity.accountList?.map( + (AccountListItem accountListItem) { + final AccountModel? account = accounts.firstWhereOrNull( + (AccountModel element) => + element.accountId == accountListItem.loginid, + ); + + if (account?.token == null) { + throw DerivAuthException( + message: 'Login is Expired', + type: AuthErrorType.expiredAccount, + ); + } + + return accountListItem.copyWith(token: account!.token); + }, + ).toList(), ); await authRepository.onLogin(_enhancedAuthorizeEntity); diff --git a/packages/deriv_auth/pubspec.yaml b/packages/deriv_auth/pubspec.yaml index 39349b3b2..e7a52565d 100644 --- a/packages/deriv_auth/pubspec.yaml +++ b/packages/deriv_auth/pubspec.yaml @@ -1,6 +1,6 @@ name: deriv_auth description: Provides deriv authentication functionalities for dart/flutter apps. -version: 6.7.10 +version: 6.7.17 environment: sdk: ">=3.0.0 <4.0.0" @@ -28,7 +28,7 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 deriv_http_client: git: @@ -39,7 +39,7 @@ dependencies: flutter_deriv_api: git: url: git@github.com:deriv-com/flutter-deriv-api.git - ref: v1.0.0 + ref: v1.1.0 deriv_web_view: git: @@ -57,13 +57,13 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_passkeys - ref: deriv_passkeys-v0.0.2+9 + ref: deriv_passkeys-v0.0.3+5 deriv_language_selector: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_language_selector - ref: deriv_language_selector-v0.0.2+7 + ref: deriv_language_selector-v0.0.2+9 flutter_bloc: ^8.1.3 flutter_svg: ^2.0.7 @@ -79,7 +79,7 @@ dependency_overrides: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 dev_dependencies: mocktail: ^1.0.3 diff --git a/packages/deriv_language_selector/CHANGELOG.md b/packages/deriv_language_selector/CHANGELOG.md index 042e415f2..d26895b3c 100644 --- a/packages/deriv_language_selector/CHANGELOG.md +++ b/packages/deriv_language_selector/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.0.2+9 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 0.0.2+8 + + - Update a dependency to the latest release. + ## 0.0.2+7 - Update a dependency to the latest release. diff --git a/packages/deriv_language_selector/pubspec.yaml b/packages/deriv_language_selector/pubspec.yaml index 65dbe3b48..69b39cafe 100644 --- a/packages/deriv_language_selector/pubspec.yaml +++ b/packages/deriv_language_selector/pubspec.yaml @@ -1,6 +1,6 @@ name: deriv_language_selector description: A package to select language for the app. It provides both UI and logic for language selection. -version: 0.0.2+7 +version: 0.0.2+9 publish_to: "none" environment: @@ -14,7 +14,7 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 shared_preferences: ^2.2.2 flutter_bloc: ^8.1.4 equatable: ^2.0.5 diff --git a/packages/deriv_localizations/lib/l10n/deriv_auth/app_fr.arb b/packages/deriv_localizations/lib/l10n/deriv_auth/app_fr.arb index 6b10d558b..be90562c9 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_auth/app_fr.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_auth/app_fr.arb @@ -14,12 +14,12 @@ "warnNotAvailableCountries": "Si vous avez des questions, contactez-nous par ", "labelLiveChat": "Chat en direct", "actionSignUpForFree": "Inscrivez-vous gratuitement", - "actionLogin": "Connexion", + "actionLogin": "Se connecter", "labelTwoFactorAuth": "Authentification à deux facteurs", "informEnterTwoFactorAuthCode": "Saisissez le code à 6 chiffres qui s'affiche sur l'application d'authentification de votre téléphone.", "labelTwoFactorAuthenticationCode": "code 2FA", "actionProceed": "Continuer", - "labelLogIn": "Connexion", + "labelLogIn": "Se connecter", "informLoginOptions": "Ou connectez-vous avec", "labelEmail": "E-mail", "labelPassword": "Mot de passe", diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ar.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ar.arb index 1941c81f8..92bcec46f 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ar.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ar.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "المؤشرات" + "labelIndicators": "المؤشرات", + "labelActive": "نشط", + "labelAll": "الكل", + "labelMomentum": "الزخم", + "labelVolatility": "التقلبات", + "labelMovingAverages": "المتوسطات المتحركة", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "مؤشر القوة النسبية (RSI)", + "labelRSI": "مؤشر القوة النسبية", + "labelBollingerBands": "البولنجر باند (BB)", + "labelBB": "ب ب", + "labelMovingAverage": "المتوسط المتحرك (MA)", + "labelMA": "ماجستير", + "infoMACD": "مؤشر MACD هو مؤشر تداول يستخدم في التحليل الفني لأسعار الأسهم. ومن المفترض أن يكشف عن التغيرات في قوة واتجاه وزخم ومدة الاتجاه في سعر السهم.", + "infoRSI": "تم نشر مؤشر القوة النسبية (RSI) بواسطة J. Welles Wilder. يتم تطبيع السعر الحالي كنسبة مئوية بين 0 و 100. إن معرف flutter_chart_id لهذا المذبذب مضلل لأنه لا يقارن الأداة بالنسبة إلى أداة أخرى أو مجموعة من الأدوات، بل يمثل السعر الحالي بالنسبة إلى القطع الحديثة الأخرى ضمن طول نافذة الاسترجاع المحددة.", + "infoBB": "يمكن استخدام مؤشر بولينجر باند (BB) لقياس مدى ارتفاع أو انخفاض السعر بالنسبة للصفقات السابقة.", + "infoMA": "يساعد المتوسط المتحرك (MA) على تحديد الاتجاه العام للسوق من خلال تصفية تقلبات الأسعار على المدى القصير. وباستخدام البيانات التاريخية، يحسب المتوسط المتحرك متوسط السعر خلال فترة محددة ويرسم خطًا على الرسم البياني. إذا تحرك خط المتوسط المتحرك المتحرك لأعلى، فهذا مؤشر على وجود اتجاه صعودي، ويكون مؤشرًا على اتجاه هبوطي إذا تحرك لأسفل. وتحدث إشارة الشراء عندما يتحرك السعر فوق خط المتوسط المتحرك.", + "infoMaximumActiveIndicatorsAdded": "لقد أضفت الحد الأقصى لعدد المؤشرات النشطة.", + "infoAddSelectedIndicator": "إضافة {indicator}", + "infoAddIndicator": "إضافة مؤشر", + "labelDeleteAllIndicators": "حذف جميع المؤشرات", + "infoDeleteAllIndicators": "سيؤدي ذلك إلى حذف جميع المؤشرات النشطة.", + "labelDeleteIndicator": "حذف المؤشر {indicator}", + "infoDeleteIndicator": "هل أنت متأكد من رغبتك في حذف هذا المؤشر؟", + "labelCancel": "إلغاء", + "labelDelete": "حذف", + "labelDeleteAll": "حذف الكل", + "infoUpto3indicatorsAllowed": "يُسمح بحد أقصى 3 مؤشرات نشطة.", + "infoNoActiveIndicators": "ليس لديك مؤشرات نشطة حتى الآن.", + "labelReset": "إعادة تعيين", + "labelApply": "قدم طلبك", + "labelOK": "حسناً", + "labelRSILine": "خط مؤشر القوة النسبية RSI", + "labelPeriod": "الفترة", + "labelMinRange": "الحد الأدنى للنطاق", + "labelMaxRange": "الحد الأقصى للنطاق", + "labelSource": "المصدر", + "labelClose": "إغلاق", + "labelOpen": "افتح", + "labelHigh": "عالية", + "labelLow": "منخفضة", + "labelHl/2": "هـ / 2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "أولك/4", + "labelShowZones": "مناطق العرض", + "labelOverbought": "الإفراط في الشراء", + "labelOversold": "المبالغة في البيع", + "labelMinSize": "الحد الأدنى للحجم", + "labelMaxSize": "الحد الأقصى للحجم", + "labelRange": "النطاق", + "labelOverboughtLine": "خط ذروة الشراء", + "labelOversoldLine": "خط المبيع الزائد", + "labelMACDLine": "خط MACD", + "labelFastMAPeriod": "فترة المتوسط المتحرك السريع", + "labelSlowMAPeriod": "فترة بطء المتوسط المتحرك البطيء", + "labelSignalLine": "خط الإشارة", + "labelSignalPeriod": "فترة الإشارة", + "labelIncreasingBar": "زيادة الشريط", + "labelDecreasingBar": "شريط تنازلي", + "labelBollingerBandsTop": "قمة بولينجر باندز", + "labelBollingerBandsMedian": "متوسط بولينجر باندز", + "labelBollingerBandsBottom": "قاع بولينجر باندز", + "labelChannelFill": "تعبئة القناة", + "labelFillColor": "لون التعبئة", + "labelStandardDeviations": "الانحرافات المعيارية", + "labelMovingAverageType": "نوع المتوسط المتحرك", + "labelMALine": "خط MA", + "labelOffset": "الأوفست", + "labelType": "النوع", + "labelSimple": "بسيطة", + "labelExponential": "الأسي", + "labelWeighted": "مرجح", + "labelHull": "هال", + "labelZeroLag": "التأخر الصفري", + "labelTimeSeries": "السلاسل الزمنية", + "labelWellesWilder": "ويلز وايلدر", + "labelVariable": "متغير", + "labelTriangular": "مثلث الشكل", + "label2Exponential": "2-الأسي", + "label3Exponential": "3-الإكسبونسي" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_bn.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_bn.arb index c406ace5d..b259eb03d 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_bn.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_bn.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "সূচক" + "labelIndicators": "সূচক", + "labelActive": "সক্রিয়", + "labelAll": "সব", + "labelMomentum": "মোমেন্টাম", + "labelVolatility": "অস্থিরতা", + "labelMovingAverages": "মুভিং গড়", + "labelMACD": "ম্যাকডি", + "labelRelativeStrengthIndex": "আপেক্ষিক শক্তি সূচক (আরএসআই)", + "labelRSI": "আরএসআই", + "labelBollingerBands": "বোলিঙ্গার ব্যান্ড (বিবি)", + "labelBB": "বিবি", + "labelMovingAverage": "মুভিং এভারেজ (এমএ)", + "labelMA": "মা", + "infoMACD": "এমএসিডি স্টকের দামের প্রযুক্তিগত বিশ্লেষণে ব্যবহৃত একটি ট্রেডিং সূচক। এটি কোনও স্টকের দামের প্রবণতার শক্তি, দিক, গতি এবং সময়কালের পরিবর্তনগুলি প্রকাশ করবে বলে মনে করা হয়।", + "infoRSI": "আপেক্ষিক শক্তি সূচক (আরএসআই) প্রকাশ করেছিলেন জে ওয়েলস ওয়াইল্ডার। বর্তমান মূল্য 0 থেকে 100 এর মধ্যে শতাংশ হিসাবে স্বাভাবিক করা হয়। এই অসিলেটরের ফ্লুটার_চার্ট_আইডি বিভ্রান্তিকর কারণ এটি অন্য যন্ত্র বা যন্ত্রের সেটের সাথে তুলনা করে না, বরং নির্বাচিত লুকব্যাক উইন্ডো দৈর্ঘ্যের মধ্যে অন্যান্য সাম্প্রতিক টুকরোগুলির তুলনায় বর্তমান দামের প্রতিনিধিত্ব করে।", + "infoBB": "পূর্ববর্তী ট্রেডগুলির তুলনায় মূল্যের উচ্চতা বা নিম্নতা পরিমাপ করতে বোলিঙ্গার ব্যান্ড (বিবি) ব্যবহার করা যেতে পারে।", + "infoMA": "মুভিং এভারেজ (এমএ) স্বল্পমেয়াদী মূল্যের ওঠানামা ফিল্টার করে সামগ্রিক বাজারের প্রবণতা সনাক্ত করতে ঐতিহাসিক ডেটা ব্যবহার করে, এটি একটি নির্দিষ্ট সময়কালে গড় মূল্য গণনা করে এবং চার্টে একটি লাইন প্লট করে। এমএ লাইন যদি উপরের দিকে চলে যায় তবে এটি একটি আপট্রেন্ডের সূচক, নীচের দিকে চলে গেলে একটি ডাউনট্রেন্ড। মূল্য এমএ লাইনের উপরে চলে গেলে একটি ক্রয় সংকেত ঘটে।", + "infoMaximumActiveIndicatorsAdded": "আপনি সর্বাধিক সংখ্যক সক্রিয় সূচক যুক্ত করেছেন।", + "infoAddSelectedIndicator": "যোগ করুন {indicator}", + "infoAddIndicator": "সূচক যোগ করুন", + "labelDeleteAllIndicators": "সমস্ত সূচক মুছুন", + "infoDeleteAllIndicators": "এটি সমস্ত সক্রিয় সূচক মুছে ফেলবে।", + "labelDeleteIndicator": "{indicator} সূচক মুছুন", + "infoDeleteIndicator": "আপনি কি নিশ্চিত যে আপনি এই সূচকটি মুছে ফেলতে চান?", + "labelCancel": "বাতিল করুন", + "labelDelete": "মুছে ফেলুন", + "labelDeleteAll": "সব মুছে ফেলুন", + "infoUpto3indicatorsAllowed": "3 টি পর্যন্ত সক্রিয় সূচক অনুমোদিত।", + "infoNoActiveIndicators": "আপনার এখনও কোনও সক্রিয় সূচক নেই।", + "labelReset": "রিসেট করুন", + "labelApply": "আবেদন করুন", + "labelOK": "ঠিক আছে", + "labelRSILine": "আরএসআই লাইন", + "labelPeriod": "সময়কাল", + "labelMinRange": "নিম্ন পরিসীমা", + "labelMaxRange": "সর্বোচ্চ ব্যাপ্তি", + "labelSource": "উৎস", + "labelClose": "বন্ধ করুন", + "labelOpen": "খোলা", + "labelHigh": "উচ্চ", + "labelLow": "নিম্ন", + "labelHl/2": "এইচএল/2", + "labelHlc/3": "এইচএলসি/3", + "labelHlcc/4": "এইচএলসিসি/4", + "labelOhlc/4": "ওএইচএলসি/4", + "labelShowZones": "অঞ্চল দেখান", + "labelOverbought": "অতিরিক্ত খরচ", + "labelOversold": "অতিরিক্ত বিক্রি", + "labelMinSize": "ন্যূনতম আকার", + "labelMaxSize": "সর্বোচ্চ আকার", + "labelRange": "পরিসীমা", + "labelOverboughtLine": "ওভারবাউট লাইন", + "labelOversoldLine": "ওভারসোল্ড লাইন", + "labelMACDLine": "এমএসিডি লাইন", + "labelFastMAPeriod": "দ্রুত এমএ পিরিয়ড", + "labelSlowMAPeriod": "ধীর এমএ পিরিয়ড", + "labelSignalLine": "সিগন্যাল লাইন", + "labelSignalPeriod": "সংকেত সময়কাল", + "labelIncreasingBar": "বর্ধমান বার", + "labelDecreasingBar": "হ্রাস করা বার", + "labelBollingerBandsTop": "বোলিংগার ব্যান্ড শীর্ষ", + "labelBollingerBandsMedian": "বোলিঙ্গার ব্যান্ডের মাঝারি", + "labelBollingerBandsBottom": "বোলিঙ্গার ব্যান্ড নীচে", + "labelChannelFill": "চ্যানেল পূরণ", + "labelFillColor": "রঙ পূরণ করুন", + "labelStandardDeviations": "মান বিচ্যুতি", + "labelMovingAverageType": "মুভিং এভারেজ প্রকার", + "labelMALine": "এমএ লাইন", + "labelOffset": "অফসেট", + "labelType": "টাইপ", + "labelSimple": "সহজ", + "labelExponential": "এক্সপোনেন্সিয়াল", + "labelWeighted": "ওজনযুক্ত", + "labelHull": "হাল", + "labelZeroLag": "জিরো ল্যাগ", + "labelTimeSeries": "টাইম সিরিজ", + "labelWellesWilder": "ওয়েলস ওয়াইল্ডার", + "labelVariable": "পরিবর্তনশীল", + "labelTriangular": "ত্রিভুজ", + "label2Exponential": "2-এক্সপোনেন্সিয়াল", + "label3Exponential": "3-এক্সপোনেন্সিয়াল" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_de.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_de.arb index ca7b35187..96ae85b04 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_de.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_de.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indikatoren" + "labelIndicators": "Indikatoren", + "labelActive": "Aktiv", + "labelAll": "Alle", + "labelMomentum": "Momentum", + "labelVolatility": "Volatilität", + "labelMovingAverages": "Gleitende Durchschnitte", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Relative Stärke Index (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bollinger Bands (BB)", + "labelBB": "BB", + "labelMovingAverage": "Gleitender Durchschnitt (MA)", + "labelMA": "MA", + "infoMACD": "Der MACD ist ein Handelsindikator, der bei der technischen Analyse von Aktienkursen verwendet wird. Er soll Veränderungen in der Stärke, Richtung, Dynamik und Dauer eines Trends bei einem Aktienkurs aufzeigen.", + "infoRSI": "Der Relative Strength Index (RSI) wurde von J. Welles Wilder veröffentlicht. Der aktuelle Kurs wird als Prozentsatz zwischen 0 und 100 normalisiert. Die flutter_chart_id dieses Oszillators ist irreführend, da sie das Instrument nicht im Verhältnis zu einem anderen Instrument oder einer Reihe von Instrumenten vergleicht, sondern den aktuellen Kurs im Verhältnis zu anderen jüngsten Stücken innerhalb des gewählten Rückblickfensters darstellt.", + "infoBB": "Bollinger Bänder (BB) können verwendet werden, um die Höhe oder Tiefe des Kurses im Vergleich zu früheren Trades zu messen.", + "infoMA": "Der gleitende Durchschnitt (MA) hilft dabei, den allgemeinen Markttrend zu erkennen, indem er kurzfristige Kursschwankungen herausfiltert. Anhand historischer Daten berechnet er den Durchschnittspreis über einen bestimmten Zeitraum und zeichnet eine Linie in den Chart ein. Bewegt sich die MA-Linie nach oben, ist dies ein Indikator für einen Aufwärtstrend, bewegt sie sich nach unten, ist dies ein Abwärtstrend. Ein Kaufsignal entsteht, wenn sich der Kurs über die MA-Linie bewegt.", + "infoMaximumActiveIndicatorsAdded": "Sie haben die maximale Anzahl von aktiven Indikatoren hinzugefügt.", + "infoAddSelectedIndicator": "{indicator}hinzufügen", + "infoAddIndicator": "Indikator hinzufügen", + "labelDeleteAllIndicators": "Alle Indikatoren löschen", + "infoDeleteAllIndicators": "Dadurch werden alle aktiven Indikatoren gelöscht.", + "labelDeleteIndicator": "Löschen {indicator} Indikator", + "infoDeleteIndicator": "Sind Sie sicher, dass Sie diesen Indikator löschen möchten?", + "labelCancel": "Abbrechen", + "labelDelete": "Löschen", + "labelDeleteAll": "Alle löschen", + "infoUpto3indicatorsAllowed": "Bis zu 3 aktive Indikatoren erlaubt.", + "infoNoActiveIndicators": "Sie haben noch keine aktiven Indikatoren.", + "labelReset": "Zurücksetzen", + "labelApply": "Anwenden", + "labelOK": "OK", + "labelRSILine": "RSI-Linie", + "labelPeriod": "Zeitraum", + "labelMinRange": "Min. Reichweite", + "labelMaxRange": "Maximale Reichweite", + "labelSource": "Quelle", + "labelClose": "Schließen Sie", + "labelOpen": "Öffnen Sie", + "labelHigh": "Hoch", + "labelLow": "Niedrig", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Zonen anzeigen", + "labelOverbought": "Überkauft", + "labelOversold": "Überverkauft", + "labelMinSize": "Minimale Größe", + "labelMaxSize": "Maximale Größe", + "labelRange": "Reichweite", + "labelOverboughtLine": "Überkaufte Linie", + "labelOversoldLine": "Überverkaufte Linie", + "labelMACDLine": "MACD-Linie", + "labelFastMAPeriod": "Schnelle MA-Periode", + "labelSlowMAPeriod": "Langsame MA-Periode", + "labelSignalLine": "Signalleitung", + "labelSignalPeriod": "Signalperiode", + "labelIncreasingBar": "Steigende Bar", + "labelDecreasingBar": "Abnehmender Balken", + "labelBollingerBandsTop": "Bollinger Bands oben", + "labelBollingerBandsMedian": "Bollinger Bands Median", + "labelBollingerBandsBottom": "Bollinger Bands unten", + "labelChannelFill": "Kanal füllen", + "labelFillColor": "Farbe ausfüllen", + "labelStandardDeviations": "Standardabweichungen", + "labelMovingAverageType": "Gleitender Durchschnitt Typ", + "labelMALine": "MA-Linie", + "labelOffset": "Versetzt", + "labelType": "Typ", + "labelSimple": "Einfach", + "labelExponential": "Exponential", + "labelWeighted": "Gewichtet", + "labelHull": "Rumpf", + "labelZeroLag": "Null Verzögerung", + "labelTimeSeries": "Zeitreihen", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variabel", + "labelTriangular": "Dreieckig", + "label2Exponential": "2-Exponential", + "label3Exponential": "3-Exponential" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_en.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_en.arb index d3fba5184..84d54e299 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_en.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_en.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indicators" + "labelIndicators": "Indicators", + "labelActive": "Active", + "labelAll": "All", + "labelMomentum": "Momentum", + "labelVolatility": "Volatility", + "labelMovingAverages": "Moving averages", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Relative Strength Index (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bollinger Bands (BB)", + "labelBB": "BB", + "labelMovingAverage": "Moving Average (MA)", + "labelMA": "MA", + "infoMACD": "MACD is a trading indicator used in technical analysis of stock prices. It is supposed to reveal changes in the strength, direction, momentum, and duration of a trend in a stock's price.", + "infoRSI": "The Relative Strength Index (RSI) was published by J. Welles Wilder. The current price is normalized as a percentage between 0 and 100. The flutter_chart_id of this oscillator is misleading because it does not compare the instrument relative to another instrument or set of instruments, but rather represents the current price relative to other recent pieces within the selected lookback window length.", + "infoBB": "Bollinger Bands (BB) can be used to measure the highness or lowness of the price relative to previous trades.", + "infoMA": "The Moving Average (MA) helps to identify the overall market trend by filtering out short-term price fluctuations. Using historical data, it calculates the average price over a specific period and plots a line on the chart. If the MA line moves upwards, it’s an indicator of an uptrend, a downtrend if it moves downwards. A buy signal occurs when the price moves above the MA line.", + "infoMaximumActiveIndicatorsAdded": "You've added the maximum number of active indicators.", + "infoAddSelectedIndicator": "Add {indicator}", + "infoAddIndicator": "Add indicator", + "labelDeleteAllIndicators": "Delete all indicators", + "infoDeleteAllIndicators": "This will delete all active indicators.", + "labelDeleteIndicator": "Delete {indicator} indicator", + "infoDeleteIndicator": "Are you sure you want to delete this indicator?", + "labelCancel": "Cancel", + "labelDelete": "Delete", + "labelDeleteAll": "Delete All", + "infoUpto3indicatorsAllowed": "Up to 3 active indicators allowed.", + "infoNoActiveIndicators": "You have no active indicators yet.", + "labelReset": "Reset", + "labelApply": "Apply", + "labelOK": "OK", + "labelRSILine": "RSI line", + "labelPeriod": "Period", + "labelMinRange": "Min range", + "labelMaxRange": "Max range", + "labelSource": "Source", + "labelClose": "Close", + "labelOpen": "Open", + "labelHigh": "High", + "labelLow": "Low", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Show Zones", + "labelOverbought": "Overbought", + "labelOversold": "Oversold", + "labelMinSize": "Min size", + "labelMaxSize": "Max size", + "labelRange": "Range", + "labelOverboughtLine": "Overbought line", + "labelOversoldLine": "Oversold line", + "labelMACDLine": "MACD line", + "labelFastMAPeriod": "Fast MA period", + "labelSlowMAPeriod": "Slow MA period", + "labelSignalLine": "Signal line", + "labelSignalPeriod": "Signal period", + "labelIncreasingBar": "Increasing bar", + "labelDecreasingBar": "Decreasing bar", + "labelBollingerBandsTop": "Bollinger Bands top", + "labelBollingerBandsMedian": "Bollinger Bands median", + "labelBollingerBandsBottom": "Bollinger Bands bottom", + "labelChannelFill": "Channel fill", + "labelFillColor": "Fill color", + "labelStandardDeviations": "Standard deviations", + "labelMovingAverageType": "Moving Average Type", + "labelMALine": "MA line", + "labelOffset": "Offset", + "labelType": "Type", + "labelSimple": "Simple", + "labelExponential": "Exponential", + "labelWeighted": "Weighted", + "labelHull": "Hull", + "labelZeroLag": "Zero Lag", + "labelTimeSeries": "Time Series", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variable", + "labelTriangular": "Triangular", + "label2Exponential": "2-Exponential", + "label3Exponential": "3-Exponential" } diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_es.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_es.arb index 9503f6aab..3fa4544ab 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_es.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_es.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indicadores" + "labelIndicators": "Indicadores", + "labelActive": "Activo", + "labelAll": "Todos", + "labelMomentum": "Impulso", + "labelVolatility": "Volatilidad", + "labelMovingAverages": "Medias móviles", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Índice de fuerza relativa (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bandas de Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Media móvil (MA)", + "labelMA": "MA", + "infoMACD": "El MACD es un indicador utilizado en el análisis técnico de las cotizaciones bursátiles. Se supone que revela los cambios en la fuerza, la dirección, el impulso y la duración de una tendencia en el precio de una acción.", + "infoRSI": "El índice de fuerza relativa (RSI) fue publicado por J. Welles Wilder. El precio actual se normaliza como un porcentaje entre 0 y 100. El flutter_chart_id de este oscilador es engañoso porque no compara el instrumento en relación con otro instrumento o conjunto de instrumentos, sino que representa el precio actual en relación con otras piezas recientes dentro de la longitud de la ventana de retroceso seleccionada.", + "infoBB": "Las Bandas de Bollinger (BB) pueden utilizarse para medir la altitud o la caída del precio en relación con operaciones anteriores.", + "infoMA": "La media móvil (MA) ayuda a identificar la tendencia general del mercado filtrando las fluctuaciones de precios a corto plazo. Utilizando datos históricos, calcula el precio medio durante un periodo específico y traza una línea en el gráfico. Si la línea MA se mueve hacia arriba, es un indicador de una tendencia alcista, una tendencia bajista si se mueve hacia abajo. Una señal de compra se produce cuando el precio se mueve por encima de la línea MA.", + "infoMaximumActiveIndicatorsAdded": "Ha añadido el número máximo de indicadores activos.", + "infoAddSelectedIndicator": "Añada {indicator}", + "infoAddIndicator": "Añadir indicador", + "labelDeleteAllIndicators": "Borrar todos los indicadores", + "infoDeleteAllIndicators": "Esto borrará todos los indicadores activos.", + "labelDeleteIndicator": "Borrar el indicador {indicator}", + "infoDeleteIndicator": "¿Está seguro de que desea eliminar este indicador?", + "labelCancel": "Cancelar", + "labelDelete": "Borrar", + "labelDeleteAll": "Borrar todo", + "infoUpto3indicatorsAllowed": "Se permiten hasta 3 indicadores activos.", + "infoNoActiveIndicators": "Aún no tiene indicadores activos.", + "labelReset": "Reinicie", + "labelApply": "Aplique", + "labelOK": "OK", + "labelRSILine": "Línea RSI", + "labelPeriod": "Periodo", + "labelMinRange": "Alcance mínimo", + "labelMaxRange": "Alcance máximo", + "labelSource": "Fuente", + "labelClose": "Cerrar", + "labelOpen": "Abra", + "labelHigh": "Alta", + "labelLow": "Bajo", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Mostrar zonas", + "labelOverbought": "Sobrecompra", + "labelOversold": "Sobreventa", + "labelMinSize": "Tamaño mínimo", + "labelMaxSize": "Tamaño máximo", + "labelRange": "Gama", + "labelOverboughtLine": "Línea de sobrecompra", + "labelOversoldLine": "Línea de sobreventa", + "labelMACDLine": "Línea MACD", + "labelFastMAPeriod": "Periodo MA rápido", + "labelSlowMAPeriod": "Periodo MA lento", + "labelSignalLine": "Línea de señales", + "labelSignalPeriod": "Periodo de señalización", + "labelIncreasingBar": "Barra creciente", + "labelDecreasingBar": "Barra decreciente", + "labelBollingerBandsTop": "Parte superior de las bandas de Bollinger", + "labelBollingerBandsMedian": "Mediana de las bandas de Bollinger", + "labelBollingerBandsBottom": "Fondo de las Bandas de Bollinger", + "labelChannelFill": "Relleno del canal", + "labelFillColor": "Color de relleno", + "labelStandardDeviations": "Desviaciones estándar", + "labelMovingAverageType": "Tipo de media móvil", + "labelMALine": "Línea MA", + "labelOffset": "Desplazamiento", + "labelType": "Tipo", + "labelSimple": "Simple", + "labelExponential": "Exponencial", + "labelWeighted": "Ponderado", + "labelHull": "Casco", + "labelZeroLag": "Retraso cero", + "labelTimeSeries": "Series temporales", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variable", + "labelTriangular": "Triangular", + "label2Exponential": "2-Exponencial", + "label3Exponential": "3-Exponencial" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_fr.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_fr.arb index 9a78c8fb2..bfbe9c750 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_fr.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_fr.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indicateurs" + "labelIndicators": "Indicateurs", + "labelActive": "Actif", + "labelAll": "Tous", + "labelMomentum": "L'élan", + "labelVolatility": "Volatilité", + "labelMovingAverages": "Moyennes mobiles", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Indice de force relative (IFR)", + "labelRSI": "RSI", + "labelBollingerBands": "Bandes de Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Moyenne mobile (MA)", + "labelMA": "MA", + "infoMACD": "Le MACD est un indicateur de trading utilisé dans l'analyse technique des cours boursiers. Il est censé révéler les changements dans la force, la direction, l'élan et la durée d'une tendance dans le prix d'une action.", + "infoRSI": "L'indice de force relative (RSI) a été publié par J. Welles Wilder. Le prix actuel est normalisé en pourcentage entre 0 et 100. Le flutter_chart_id de cet oscillateur est trompeur car il ne compare pas l'instrument par rapport à un autre instrument ou à un ensemble d'instruments, mais représente plutôt le prix actuel par rapport à d'autres pièces récentes dans la longueur de la fenêtre d'observation sélectionnée.", + "infoBB": "Les bandes de Bollinger (BB) peuvent être utilisées pour mesurer la hausse ou la baisse du prix par rapport aux transactions précédentes.", + "infoMA": "La moyenne mobile (MA) permet d'identifier la tendance générale du marché en filtrant les fluctuations de prix à court terme. À l'aide de données historiques, elle calcule le prix moyen sur une période donnée et trace une ligne sur le graphique. Si la ligne de la MA se déplace vers le haut, il s'agit d'un indicateur de tendance haussière, et si elle se déplace vers le bas, il s'agit d'un indicateur de tendance baissière. Un signal d'achat se produit lorsque le prix passe au-dessus de la ligne MA.", + "infoMaximumActiveIndicatorsAdded": "Vous avez ajouté le nombre maximum d'indicateurs actifs.", + "infoAddSelectedIndicator": "Ajoutez {indicator}", + "infoAddIndicator": "Ajouter un indicateur", + "labelDeleteAllIndicators": "Supprimer tous les indicateurs", + "infoDeleteAllIndicators": "Cette opération supprime tous les indicateurs actifs.", + "labelDeleteIndicator": "Indicateur de suppression {indicator}", + "infoDeleteIndicator": "Êtes-vous sûr de vouloir supprimer cet indicateur ?", + "labelCancel": "Annuler", + "labelDelete": "Supprimer", + "labelDeleteAll": "Supprimer tout", + "infoUpto3indicatorsAllowed": "Jusqu'à 3 indicateurs actifs sont autorisés.", + "infoNoActiveIndicators": "Vous n'avez pas encore d'indicateurs actifs.", + "labelReset": "Remise à zéro", + "labelApply": "Appliquer", + "labelOK": "OK", + "labelRSILine": "Ligne RSI", + "labelPeriod": "Période", + "labelMinRange": "Plage minimale", + "labelMaxRange": "Portée maximale", + "labelSource": "Source", + "labelClose": "Fermer", + "labelOpen": "Ouvrir", + "labelHigh": "Haut", + "labelLow": "Faible", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Afficher les zones", + "labelOverbought": "Surachat", + "labelOversold": "Survente", + "labelMinSize": "Taille minimale", + "labelMaxSize": "Taille maximale", + "labelRange": "Gamme", + "labelOverboughtLine": "Ligne de surachat", + "labelOversoldLine": "Ligne de survente", + "labelMACDLine": "Ligne MACD", + "labelFastMAPeriod": "Période d'AM rapide", + "labelSlowMAPeriod": "Période d'AM lente", + "labelSignalLine": "Ligne de signal", + "labelSignalPeriod": "Période du signal", + "labelIncreasingBar": "Augmentation de la barre", + "labelDecreasingBar": "Barre décroissante", + "labelBollingerBandsTop": "Sommet des bandes de Bollinger", + "labelBollingerBandsMedian": "Bandes de Bollinger médianes", + "labelBollingerBandsBottom": "Fond des bandes de Bollinger", + "labelChannelFill": "Remplissage du canal", + "labelFillColor": "Couleur de remplissage", + "labelStandardDeviations": "Écarts types", + "labelMovingAverageType": "Type de moyenne mobile", + "labelMALine": "Ligne MA", + "labelOffset": "Décalage", + "labelType": "Type", + "labelSimple": "Simple", + "labelExponential": "Exponentiel", + "labelWeighted": "Pondéré", + "labelHull": "Coque", + "labelZeroLag": "Zéro lag", + "labelTimeSeries": "Séries chronologiques", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variable", + "labelTriangular": "Triangulaire", + "label2Exponential": "2-Exponentiel", + "label3Exponential": "3-Exponentiel" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_it.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_it.arb index 7dae053d1..dde338132 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_it.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_it.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indicatori" + "labelIndicators": "Indicatori", + "labelActive": "Attivo", + "labelAll": "Tutti", + "labelMomentum": "Momento", + "labelVolatility": "Volatilità", + "labelMovingAverages": "Medie mobili", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Indice di forza relativa (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bande di Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Media mobile (MA)", + "labelMA": "MA", + "infoMACD": "Il MACD è un indicatore di trading utilizzato nell'analisi tecnica dei prezzi delle azioni. Si suppone che riveli i cambiamenti nella forza, nella direzione, nello slancio e nella durata di una tendenza nel prezzo di un'azione.", + "infoRSI": "L'Indice di Forza Relativa (RSI) è stato pubblicato da J. Welles Wilder. Il prezzo corrente viene normalizzato come percentuale tra 0 e 100. Il flutter_chart_id di questo oscillatore è fuorviante perché non confronta lo strumento rispetto ad un altro strumento o ad un insieme di strumenti, ma rappresenta piuttosto il prezzo corrente rispetto ad altri pezzi recenti all'interno della lunghezza della finestra di lookback selezionata.", + "infoBB": "Le Bande di Bollinger (BB) possono essere utilizzate per misurare l'altezza o la debolezza del prezzo rispetto alle contrattazioni precedenti.", + "infoMA": "La media mobile (MA) aiuta a identificare la tendenza generale del mercato, filtrando le fluttuazioni di prezzo a breve termine. Utilizzando i dati storici, calcola il prezzo medio in un periodo specifico e traccia una linea sul grafico. Se la linea MA si muove verso l'alto, è un indicatore di una tendenza al rialzo, di una tendenza al ribasso se si muove verso il basso. Un segnale di acquisto si verifica quando il prezzo si muove al di sopra della linea MA.", + "infoMaximumActiveIndicatorsAdded": "Ha aggiunto il numero massimo di indicatori attivi.", + "infoAddSelectedIndicator": "Aggiungi {indicator}", + "infoAddIndicator": "Aggiungi indicatore", + "labelDeleteAllIndicators": "Cancellare tutti gli indicatori", + "infoDeleteAllIndicators": "Questo eliminerà tutti gli indicatori attivi.", + "labelDeleteIndicator": "Cancellare l'indicatore {indicator}", + "infoDeleteIndicator": "È sicuro di voler eliminare questo indicatore?", + "labelCancel": "Annullamento", + "labelDelete": "Cancellare", + "labelDeleteAll": "Cancella tutto", + "infoUpto3indicatorsAllowed": "Sono consentiti fino a 3 indicatori attivi.", + "infoNoActiveIndicators": "Non ha ancora indicatori attivi.", + "labelReset": "Azzeramento", + "labelApply": "Applicare", + "labelOK": "OK", + "labelRSILine": "Linea RSI", + "labelPeriod": "Periodo", + "labelMinRange": "Intervallo minimo", + "labelMaxRange": "Gamma massima", + "labelSource": "Fonte", + "labelClose": "Chiudere", + "labelOpen": "Aperto", + "labelHigh": "Alto", + "labelLow": "Basso", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Mostra le zone", + "labelOverbought": "Sovracomprato", + "labelOversold": "In ipervenduto", + "labelMinSize": "Dimensione minima", + "labelMaxSize": "Dimensione massima", + "labelRange": "Gamma", + "labelOverboughtLine": "Linea di ipercomprato", + "labelOversoldLine": "Linea di ipervenduto", + "labelMACDLine": "Linea MACD", + "labelFastMAPeriod": "Periodo di MA veloce", + "labelSlowMAPeriod": "Periodo di MA lento", + "labelSignalLine": "Linea di segnale", + "labelSignalPeriod": "Periodo del segnale", + "labelIncreasingBar": "Barra di aumento", + "labelDecreasingBar": "Barra decrescente", + "labelBollingerBandsTop": "Bande di Bollinger top", + "labelBollingerBandsMedian": "Bande di Bollinger mediane", + "labelBollingerBandsBottom": "Fondo delle Bande di Bollinger", + "labelChannelFill": "Riempimento del canale", + "labelFillColor": "Colore di riempimento", + "labelStandardDeviations": "Deviazioni standard", + "labelMovingAverageType": "Tipo di media mobile", + "labelMALine": "Linea MA", + "labelOffset": "Offset", + "labelType": "Tipo", + "labelSimple": "Semplice", + "labelExponential": "Esponenziale", + "labelWeighted": "Ponderato", + "labelHull": "Scafo", + "labelZeroLag": "Zero Lag", + "labelTimeSeries": "Serie temporale", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variabile", + "labelTriangular": "Triangolare", + "label2Exponential": "2-Esponenziale", + "label3Exponential": "3-Esponenziale" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ko.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ko.arb index 1df3fd1b7..3590876b7 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ko.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ko.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "지표" + "labelIndicators": "지표", + "labelActive": "활성", + "labelAll": "모두", + "labelMomentum": "모멘텀", + "labelVolatility": "변동성", + "labelMovingAverages": "이동 평균", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "상대 강도 지수(RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "볼린저 밴드(BB)", + "labelBB": "BB", + "labelMovingAverage": "이동 평균(MA)", + "labelMA": "MA", + "infoMACD": "MACD는 주가의 기술적 분석에 사용되는 트레이딩 지표입니다. 이는 주식 가격 추세의 강도, 방향, 모멘텀, 지속 기간의 변화를 나타내는 지표입니다.", + "infoRSI": "상대강도지수(RSI)는 J. 웰즈 와일더가 발표했습니다. 현재 가격은 0에서 100 사이의 백분율로 정규화됩니다. 이 오실레이터의 flutter_chart_id는 다른 상품 또는 상품 세트와 비교하는 것이 아니라 선택한 룩백 윈도우 길이 내의 다른 최근 상품과 비교한 현재 가격을 나타내므로 오해의 소지가 있습니다.", + "infoBB": "볼린저 밴드(BB)는 이전 거래 대비 가격의 고점 또는 저점을 측정하는 데 사용할 수 있습니다.", + "infoMA": "이동평균(MA)은 단기적인 가격 변동을 걸러내어 전체 시장 추세를 파악하는 데 도움이 됩니다. 과거 데이터를 사용하여 특정 기간 동안의 평균 가격을 계산하고 차트에 선을 표시합니다. MA 선이 위로 이동하면 상승 추세, 아래로 이동하면 하락 추세의 지표입니다. 가격이 MA 선 위로 이동하면 매수 신호가 발생합니다.", + "infoMaximumActiveIndicatorsAdded": "활성 지표의 최대 개수를 추가했습니다.", + "infoAddSelectedIndicator": "{indicator}추가", + "infoAddIndicator": "표시기 추가", + "labelDeleteAllIndicators": "모든 지표 삭제", + "infoDeleteAllIndicators": "이렇게 하면 모든 활성 표시기가 삭제됩니다.", + "labelDeleteIndicator": "{indicator} 표시기 삭제", + "infoDeleteIndicator": "이 표시기를 삭제하시겠습니까?", + "labelCancel": "취소", + "labelDelete": "삭제", + "labelDeleteAll": "모두 삭제", + "infoUpto3indicatorsAllowed": "활성 표시기는 최대 3개까지 허용됩니다.", + "infoNoActiveIndicators": "아직 활성화된 지표가 없습니다.", + "labelReset": "초기화", + "labelApply": "신청하기", + "labelOK": "확인", + "labelRSILine": "RSI 라인", + "labelPeriod": "기간", + "labelMinRange": "최소 범위", + "labelMaxRange": "최대 범위", + "labelSource": "출처", + "labelClose": "닫기", + "labelOpen": "열기", + "labelHigh": "높음", + "labelLow": "낮음", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "영역 표시", + "labelOverbought": "과매수", + "labelOversold": "과매도", + "labelMinSize": "최소 크기", + "labelMaxSize": "최대 크기", + "labelRange": "범위", + "labelOverboughtLine": "과매수 라인", + "labelOversoldLine": "과매도 라인", + "labelMACDLine": "MACD 라인", + "labelFastMAPeriod": "빠른 MA 기간", + "labelSlowMAPeriod": "느린 MA 기간", + "labelSignalLine": "신호 라인", + "labelSignalPeriod": "신호 기간", + "labelIncreasingBar": "바 증가", + "labelDecreasingBar": "바 감소", + "labelBollingerBandsTop": "볼린저 밴드 상단", + "labelBollingerBandsMedian": "볼린저 밴드 중앙값", + "labelBollingerBandsBottom": "볼린저 밴드 하단", + "labelChannelFill": "채널 채우기", + "labelFillColor": "채우기 색상", + "labelStandardDeviations": "표준 편차", + "labelMovingAverageType": "이동 평균 유형", + "labelMALine": "MA 라인", + "labelOffset": "오프셋", + "labelType": "유형", + "labelSimple": "Simple", + "labelExponential": "지수", + "labelWeighted": "가중치", + "labelHull": "Hull", + "labelZeroLag": "제로 랙", + "labelTimeSeries": "시계열", + "labelWellesWilder": "웰즈 와일더", + "labelVariable": "변수", + "labelTriangular": "삼각형", + "label2Exponential": "2-지수", + "label3Exponential": "3-지수" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pl.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pl.arb index 91d1d83c1..a839f9a3d 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pl.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pl.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Wskaźniki" + "labelIndicators": "Wskaźniki", + "labelActive": "Aktywny", + "labelAll": "Wszystko", + "labelMomentum": "Pęd", + "labelVolatility": "Zmienność", + "labelMovingAverages": "Średnie kroczące", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Względny wskaźnik siły (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Zespoły Bollingera (BB)", + "labelBB": "BB", + "labelMovingAverage": "Średnia ruchoma (MA)", + "labelMA": "MA", + "infoMACD": "MACD jest wskaźnikiem handlowym wykorzystywanym w technicznej analizie cen akcji. Ma ujawniać zmiany w sile, kierunku, pędzie i czasie trwania trendu w cenie akcji.", + "infoRSI": "Relative Strength Index (RSI) został opublikowany przez J. Wellesa Wildera. Aktualna cena jest znormalizowana jako procent od 0 do 100. Flutter_chart_id tego oscylatora jest mylący, ponieważ nie porównuje instrumentu względem innego instrumentu lub zestawu instrumentów, ale reprezentuje aktualną cenę w stosunku do innych ostatnich elementów w wybranej długości okna przeglądającego.", + "infoBB": "Pasma Bollingera (BB) można wykorzystać do pomiaru wysokości lub niskiej ceny w stosunku do poprzednich transakcji.", + "infoMA": "Średnia krocząca (MA) pomaga zidentyfikować ogólny trend rynkowy poprzez filtrowanie krótkoterminowych wahań cen. Korzystając z danych historycznych, oblicza średnią cenę w określonym okresie i wykreśla linię na wykresie. Jeśli linia MA porusza się w górę, jest to wskaźnik trendu wzrostowego, trendu spadkowego, jeśli porusza się w dół. Sygnał zakupu pojawia się, gdy cena przesuwa się powyżej linii MA.", + "infoMaximumActiveIndicatorsAdded": "Dodano maksymalną liczbę aktywnych wskaźników.", + "infoAddSelectedIndicator": "Dodaj {indicator}", + "infoAddIndicator": "Dodaj wskaźnik", + "labelDeleteAllIndicators": "Usuń wszystkie wskaźniki", + "infoDeleteAllIndicators": "Spowoduje to usunięcie wszystkich aktywnych wskaźników.", + "labelDeleteIndicator": "Usuń wskaźnik {indicator}", + "infoDeleteIndicator": "Czy na pewno chcesz usunąć ten wskaźnik?", + "labelCancel": "Anuluj", + "labelDelete": "Usuń", + "labelDeleteAll": "Usuń wszystko", + "infoUpto3indicatorsAllowed": "Dozwolone jest do 3 aktywnych wskaźników.", + "infoNoActiveIndicators": "Nie masz jeszcze aktywnych wskaźników.", + "labelReset": "Resetuj", + "labelApply": "Zastosuj", + "labelOK": "DOBRZE", + "labelRSILine": "Linia RSI", + "labelPeriod": "Kropka", + "labelMinRange": "Minimalny zasięg", + "labelMaxRange": "Maksymalny zasięg", + "labelSource": "Źródło", + "labelClose": "Zamknij", + "labelOpen": "Otwórz", + "labelHigh": "Wysoki", + "labelLow": "Niski", + "labelHl/2": "Hl/2", + "labelHlc/3": "HLC/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Pokaż strefy", + "labelOverbought": "Wykupione", + "labelOversold": "Wyprzedane", + "labelMinSize": "Minimalny rozmiar", + "labelMaxSize": "Maksymalny rozmiar", + "labelRange": "Zasięg", + "labelOverboughtLine": "Linia wykupiona", + "labelOversoldLine": "Linia wyprzedana", + "labelMACDLine": "Linia MACD", + "labelFastMAPeriod": "Szybki okres MA", + "labelSlowMAPeriod": "Powolny okres MA", + "labelSignalLine": "Linia sygnałowa", + "labelSignalPeriod": "Okres sygnału", + "labelIncreasingBar": "Zwiększanie paska", + "labelDecreasingBar": "Malejący pasek", + "labelBollingerBandsTop": "Bollinger Bands Top", + "labelBollingerBandsMedian": "Mediana pasm Bollingera", + "labelBollingerBandsBottom": "Dolne paski Bollingera", + "labelChannelFill": "Wypełnienie kanału", + "labelFillColor": "Kolor wypełnienia", + "labelStandardDeviations": "Odchylenia standardowe", + "labelMovingAverageType": "Typ średniej ruchomej", + "labelMALine": "Linia MA", + "labelOffset": "Przesunięcie", + "labelType": "Typ", + "labelSimple": "Prosty", + "labelExponential": "wykładniczy", + "labelWeighted": "ważony", + "labelHull": "Kadłub", + "labelZeroLag": "Zero opóźnienia", + "labelTimeSeries": "Szereg czasowy", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Zmienna", + "labelTriangular": "Trójkątne", + "label2Exponential": "2-wykładniczy", + "label3Exponential": "3-wykładniczy" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pt.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pt.arb index 9503f6aab..97883fce3 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pt.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_pt.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Indicadores" + "labelIndicators": "Indicadores", + "labelActive": "Ativo", + "labelAll": "Todos", + "labelMomentum": "Momento", + "labelVolatility": "Volatilidade", + "labelMovingAverages": "Médias móveis", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Índice de Força Relativa (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bandas de Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Média móvel (MA)", + "labelMA": "MA", + "infoMACD": "O MACD é um indicador de negociação utilizado na análise técnica dos preços das acções. É suposto revelar alterações na força, direção, impulso e duração de uma tendência no preço de uma ação.", + "infoRSI": "O Índice de Força Relativa (RSI) foi publicado por J. Welles Wilder. O preço atual é normalizado como uma percentagem entre 0 e 100. O flutter_chart_id deste oscilador é enganador porque não compara o instrumento em relação a outro instrumento ou conjunto de instrumentos, mas sim representa o preço atual em relação a outras peças recentes dentro do comprimento da janela de lookback selecionada.", + "infoBB": "As Bandas de Bollinger (BB) podem ser utilizadas para medir a alta ou a baixa do preço relativamente a transacções anteriores.", + "infoMA": "A média móvel (MA) ajuda a identificar a tendência geral do mercado, filtrando as flutuações de preços a curto prazo. Utilizando dados históricos, calcula o preço médio durante um período específico e traça uma linha no gráfico. Se a linha MA se mover para cima, é um indicador de uma tendência de subida, uma tendência de descida se se mover para baixo. Um sinal de compra ocorre quando o preço se move acima da linha MA.", + "infoMaximumActiveIndicatorsAdded": "Adicionou o número máximo de indicadores activos.", + "infoAddSelectedIndicator": "Adicione {indicator}", + "infoAddIndicator": "Adicionar indicador", + "labelDeleteAllIndicators": "Eliminar todos os indicadores", + "infoDeleteAllIndicators": "Esta ação elimina todos os indicadores activos.", + "labelDeleteIndicator": "Apague o indicador {indicator}", + "infoDeleteIndicator": "Tem a certeza de que pretende eliminar este indicador?", + "labelCancel": "Cancelar", + "labelDelete": "Eliminar", + "labelDeleteAll": "Eliminar tudo", + "infoUpto3indicatorsAllowed": "São permitidos até 3 indicadores activos.", + "infoNoActiveIndicators": "Ainda não tem indicadores activos.", + "labelReset": "Repor", + "labelApply": "Aplicar", + "labelOK": "OK", + "labelRSILine": "Linha RSI", + "labelPeriod": "Período", + "labelMinRange": "Intervalo mínimo", + "labelMaxRange": "Alcance máximo", + "labelSource": "Fonte", + "labelClose": "Fechar", + "labelOpen": "Aberto", + "labelHigh": "Elevado", + "labelLow": "Baixo", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Mostrar zonas", + "labelOverbought": "Sobrecomprado", + "labelOversold": "Sobrevenda", + "labelMinSize": "Tamanho mínimo", + "labelMaxSize": "Tamanho máximo", + "labelRange": "Alcance", + "labelOverboughtLine": "Linha de sobrecompra", + "labelOversoldLine": "Linha de sobrevenda", + "labelMACDLine": "Linha MACD", + "labelFastMAPeriod": "Período MA rápido", + "labelSlowMAPeriod": "Período MA lento", + "labelSignalLine": "Linha de sinal", + "labelSignalPeriod": "Período do sinal", + "labelIncreasingBar": "Aumentar a barra", + "labelDecreasingBar": "Barra decrescente", + "labelBollingerBandsTop": "Topo das Bandas de Bollinger", + "labelBollingerBandsMedian": "Mediana das bandas de Bollinger", + "labelBollingerBandsBottom": "Fundo do Bollinger Bands", + "labelChannelFill": "Enchimento do canal", + "labelFillColor": "Cor de preenchimento", + "labelStandardDeviations": "Desvios-padrão", + "labelMovingAverageType": "Tipo de média móvel", + "labelMALine": "Linha MA", + "labelOffset": "Desvio", + "labelType": "Tipo", + "labelSimple": "Simples", + "labelExponential": "Exponencial", + "labelWeighted": "Ponderado", + "labelHull": "Casco", + "labelZeroLag": "Desfasamento zero", + "labelTimeSeries": "Séries temporais", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Variável", + "labelTriangular": "Triangular", + "label2Exponential": "2-Exponencial", + "label3Exponential": "3-Exponencial" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ru.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ru.arb index 4164941a3..f6c858122 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ru.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_ru.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Индикаторы" + "labelIndicators": "Индикаторы", + "labelActive": "Активный", + "labelAll": "Все", + "labelMomentum": "Momentum", + "labelVolatility": "Волатильность", + "labelMovingAverages": "Скользящие средние", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Индекс относительной силы (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Полосы Боллинджера (BB)", + "labelBB": "BB", + "labelMovingAverage": "Скользящая средняя (MA)", + "labelMA": "MA", + "infoMACD": "MACD - это торговый индикатор, используемый в техническом анализе цен на акции. Он призван выявлять изменения в силе, направлении, импульсе и продолжительности тренда в цене акции.", + "infoRSI": "Индекс относительной силы (RSI) был опубликован Дж. Уэллсом Уайлдером. Текущая цена нормируется в процентах от 0 до 100. Flutter_chart_id этого осциллятора вводит в заблуждение, поскольку он не сравнивает инструмент относительно другого инструмента или набора инструментов, а скорее представляет текущую цену относительно других недавних фигур в пределах выбранной длины окна обратного просмотра.", + "infoBB": "Полосы Боллинджера (Bollinger Bands, BB) можно использовать для измерения высоты или низкости цены по отношению к предыдущим сделкам.", + "infoMA": "Скользящая средняя (MA) помогает определить общую тенденцию рынка, отсеивая краткосрочные колебания цен. Используя исторические данные, она рассчитывает среднюю цену за определенный период и наносит линию на график. Если линия MA движется вверх, это индикатор восходящего тренда, если вниз - нисходящего. Сигнал к покупке возникает, когда цена движется выше линии MA.", + "infoMaximumActiveIndicatorsAdded": "Вы добавили максимальное количество активных индикаторов.", + "infoAddSelectedIndicator": "Добавить {indicator}", + "infoAddIndicator": "Добавьте индикатор", + "labelDeleteAllIndicators": "Удалите все индикаторы", + "infoDeleteAllIndicators": "Это удалит все активные индикаторы.", + "labelDeleteIndicator": "Индикатор удаления {indicator}", + "infoDeleteIndicator": "Вы уверены, что хотите удалить этот индикатор?", + "labelCancel": "Отмена", + "labelDelete": "Удалить", + "labelDeleteAll": "Удалить все", + "infoUpto3indicatorsAllowed": "Допускается до 3 активных индикаторов.", + "infoNoActiveIndicators": "У Вас пока нет активных индикаторов.", + "labelReset": "Сброс", + "labelApply": "Применить", + "labelOK": "OK", + "labelRSILine": "Линия RSI", + "labelPeriod": "Период", + "labelMinRange": "Минимальный диапазон", + "labelMaxRange": "Максимальный диапазон", + "labelSource": "Источник", + "labelClose": "Закрыть", + "labelOpen": "Открыть", + "labelHigh": "Высокий", + "labelLow": "Низкий", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Показать зоны", + "labelOverbought": "Перекупленность", + "labelOversold": "Перепроданность", + "labelMinSize": "Минимальный размер", + "labelMaxSize": "Максимальный размер", + "labelRange": "Диапазон", + "labelOverboughtLine": "Линия перекупленности", + "labelOversoldLine": "Линия перепроданности", + "labelMACDLine": "Линия MACD", + "labelFastMAPeriod": "Быстрый период MA", + "labelSlowMAPeriod": "Медленный период MA", + "labelSignalLine": "Сигнальная линия", + "labelSignalPeriod": "Период сигнала", + "labelIncreasingBar": "Увеличивающаяся планка", + "labelDecreasingBar": "Уменьшающаяся планка", + "labelBollingerBandsTop": "Вершина Bollinger Bands", + "labelBollingerBandsMedian": "Медиана полос Боллинджера", + "labelBollingerBandsBottom": "Дно полос Боллинджера", + "labelChannelFill": "Заполнение канала", + "labelFillColor": "Цвет заливки", + "labelStandardDeviations": "Стандартные отклонения", + "labelMovingAverageType": "Тип скользящей средней", + "labelMALine": "Линия MA", + "labelOffset": "Смещение", + "labelType": "Тип", + "labelSimple": "Простой", + "labelExponential": "Экспоненциальный", + "labelWeighted": "Взвешенный", + "labelHull": "Корпус", + "labelZeroLag": "Нулевая задержка", + "labelTimeSeries": "Временные ряды", + "labelWellesWilder": "Уэллс Уайлдер", + "labelVariable": "Переменная", + "labelTriangular": "Треугольный", + "label2Exponential": "2-Экспоненциальный", + "label3Exponential": "3-экспоненциальный" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_si.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_si.arb index 2571da265..f9a39fea1 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_si.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_si.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "දර්ශක" + "labelIndicators": "දර්ශක", + "labelActive": "ක්රියාකාරී", + "labelAll": "සියල්ලම", + "labelMomentum": "ගම්යතාව", + "labelVolatility": "අස්ථාවරත්වය", + "labelMovingAverages": "චලනය වන සාමාන්යයන්", + "labelMACD": "මැක්ඩී", + "labelRelativeStrengthIndex": "සාපේක්ෂ ශක්ති දර්ශකය (RSI)", + "labelRSI": "ආර්එස්අයි", + "labelBollingerBands": "බොලින්ගර් බෑන්ඩ් (බීබී)", + "labelBB": "BB", + "labelMovingAverage": "චලනය වන සාමාන්යය (MA)", + "labelMA": "මා", + "infoMACD": "MACD යනු කොටස් මිල ගණන් පිළිබඳ තාක්ෂණික විශ්ලේෂණයේදී භාවිතා කරන වෙළඳ දර්ශකයකි. එය කොටස් මිලෙහි ප්රවණතාවයේ ශක්තිය, දිශාව, ගම්යතාව සහ කාලසීමාවේ වෙනස්කම් හෙළි කිරීමට නියමිතය.", + "infoRSI": "සාපේක්ෂ ශක්ති දර්ශකය (RSI) ප්රකාශයට පත් කරන ලද්දේ ජේ වෙල්ස් වයිල්ඩර් විසිනි. වර්තමාන මිල 0 සහ 100 අතර ප්රතිශතයක් ලෙස සාමාන්යකරණය කර ඇත. මෙම ඔස්කිලේටරයේ flutter_chart_id නොමඟ යන්නේ එය වෙනත් උපකරණයක් හෝ උපකරණ කට්ටලයකට සාපේක්ෂව උපකරණය සංසන්දනය නොකරන නිසා, ඒ වෙනුවට තෝරාගත් lookback කවුළුව දිග තුළ අනෙකුත් මෑත කෑලිවලට සාපේක්ෂව වත්මන් මිල නියෝජනය කරයි.", + "infoBB": "පෙර වෙළඳාම් වලට සාපේක්ෂව මිලෙහි උසස්කම හෝ පහත් බව මැනීම සඳහා බොලින්ගර් බෑන්ඩ් (බීබී) භාවිතා කළ හැකිය.", + "infoMA": "චලනය වන සාමාන්යය (MA) කෙටි කාලීන මිල උච්චාවචනයන් පෙරීම මගින් සමස්ත වෙළඳපල ප්රවණතාව හඳුනා ගැනීමට උපකාරී වේ. ඓතිහාසික දත්ත භාවිතා කරමින්, එය නිශ්චිත කාල පරිච්ඡේදයක් පුරා සාමාන්ය මිල ගණනය කර ප්රස්ථාරයේ රේඛාවක් සකස් කරයි. MA රේඛාව ඉහළට ගමන් කරන්නේ නම් එය uptrend ක දර්ශකයක්, පහළට ගමන් කරන්නේ නම් downtrend එකක්. මිල MA රේඛාවට ඉහළින් ගමන් කරන විට මිලදී ගැනීමේ සංඥාවක් සිදු වේ.", + "infoMaximumActiveIndicatorsAdded": "ඔබ උපරිම ක්රියාකාරී දර්ශක සංඛ්යාව එකතු කර ඇත.", + "infoAddSelectedIndicator": "{indicator}එකතු කරන්න", + "infoAddIndicator": "දර්ශකය එක් කරන්න", + "labelDeleteAllIndicators": "සියලුම දර්ශක මකා දමන්න", + "infoDeleteAllIndicators": "මෙය සියලුම ක්රියාකාරී දර්ශක මකා දමනු ඇත.", + "labelDeleteIndicator": "{indicator} දර්ශකය මකන්න", + "infoDeleteIndicator": "ඔබට මෙම දර්ශකය මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?", + "labelCancel": "අවලංගු කරන්න", + "labelDelete": "මකන්න", + "labelDeleteAll": "සියල්ල මකා දමන්න", + "infoUpto3indicatorsAllowed": "ක්රියාකාරී දර්ශක 3 ක් දක්වා අවසර ඇත.", + "infoNoActiveIndicators": "ඔබට තවමත් ක්රියාකාරී දර්ශක නොමැත.", + "labelReset": "යළි පිහිටුවන්න", + "labelApply": "අයදුම් කරන්න", + "labelOK": "හරි", + "labelRSILine": "ආර්එස්අයි රේඛාව", + "labelPeriod": "කාල සීමාව", + "labelMinRange": "අවම පරාසය", + "labelMaxRange": "උපරිම පරාසය", + "labelSource": "මූලාශ්රය", + "labelClose": "වසා දමන්න", + "labelOpen": "විවෘත කරන්න", + "labelHigh": "ඉහළ", + "labelLow": "අඩුයි", + "labelHl/2": "එච්එල්/2", + "labelHlc/3": "එච්එල්සී/3", + "labelHlcc/4": "එච්එල්සී/4", + "labelOhlc/4": "ඕඑච්එල්සී/4", + "labelShowZones": "කලාප පෙන්වන්න", + "labelOverbought": "අධික ලෙස මිල දී ගනු ලැබේ", + "labelOversold": "අධික ලෙස විකුණා ඇත", + "labelMinSize": "අවම ප්රමාණය", + "labelMaxSize": "උපරිම ප්රමාණය", + "labelRange": "පරාසය", + "labelOverboughtLine": "අධික ලෙස මිලදී ගත් රේඛාව", + "labelOversoldLine": "අධි විකුණුම් රේඛාව", + "labelMACDLine": "MACD රේඛාව", + "labelFastMAPeriod": "වේගවත් MA කාල පරිච්ඡේදය", + "labelSlowMAPeriod": "මන්දගාමී MA කාලය", + "labelSignalLine": "සංඥා රේඛාව", + "labelSignalPeriod": "සංඥා කාලය", + "labelIncreasingBar": "තීරුව වැඩි කිරීම", + "labelDecreasingBar": "බාර් අඩුවීම", + "labelBollingerBandsTop": "බොලින්ගර් බෑන්ඩ් ටොප්", + "labelBollingerBandsMedian": "බොලින්ගර් බෑන්ඩ් මධ්යන්ය", + "labelBollingerBandsBottom": "බොලින්ගර් බෑන්ඩ්ස් පහළ", + "labelChannelFill": "නාලිකා පිරවීම", + "labelFillColor": "වර්ණය පුරවන්න", + "labelStandardDeviations": "සම්මත අපගමනය", + "labelMovingAverageType": "චලනය වන සාමාන්ය වර්ගය", + "labelMALine": "එම්ඒ රේඛාව", + "labelOffset": "ඕෆ්සෙට්", + "labelType": "වර්ගය", + "labelSimple": "සරල", + "labelExponential": "එක්ස්පේන්ෂල්", + "labelWeighted": "බර බර", + "labelHull": "හල්", + "labelZeroLag": "ශුරෝ ලැග්", + "labelTimeSeries": "කාල මාලාව", + "labelWellesWilder": "වෙල්ස් වයිල්ඩර්", + "labelVariable": "විචල්ය", + "labelTriangular": "ත්රිකෝණාකාර", + "label2Exponential": "2-එක්ස්පෙන්ෂනල්", + "label3Exponential": "3-එක්ස්පෙන්ෂනල්" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_sw.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_sw.arb index c047b5c14..91f0f5f7e 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_sw.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_sw.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Viashiria" + "labelIndicators": "Viashiria", + "labelActive": "Inafanya kazi", + "labelAll": "Wote", + "labelMomentum": "Mwendo", + "labelVolatility": "Ubadilishaji", + "labelMovingAverages": "Wastani wa kusonga", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Kielelezo cha Nguvu ya Uhusiano (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bendi za Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Wastani wa kusonga (MA)", + "labelMA": "MA", + "infoMACD": "MACD ni kiashiria cha biashara kinachotumiwa katika uchambuzi wa kiufundi wa bei za hisa. Inapaswa kufichua mabadiliko katika nguvu, mwelekeo, kasi, na muda wa mwenendo wa bei ya hisa.", + "infoRSI": "Fahirisi ya Nguvu ya Relay (RSI) ilichapishwa na J. Welles Wilder. Bei ya sasa imeorodheshwa kama asilimia kati ya 0 na 100. Flutter_chart_id ya oscillator hii inatoa kwa sababu hailinganishi chombo kinachohusiana na chombo kingine au seti ya vyombo, lakini badala yake inawakilisha bei ya sasa ikilinganishwa na vipande vingine vya hivi karibuni ndani ya urefu wa dirisha lililochaguliwa.", + "infoBB": "Bendi za Bollinger (BB) zinaweza kutumika kupima juu au chini wa bei kulinganishwa na biashara zilizopita.", + "infoMA": "Wastani wa Kusonga (MA) husaidia kutambua mwenendo wa jumla wa soko kwa kuchuja mabadiliko ya bei ya muda mfupi. Kutumia data ya kihistoria, inahesabu bei ya wastani kwa kipindi maalum na inapanga mstari kwenye chati. Ikiwa mstari wa MA unasonga juu, ni kiashiria cha kuongezeka, mwenendo wa kushuka ikiwa unasonga chini. Ishara ya ununuzi hutokea wakati bei inapohamia juu ya mstari wa MA.", + "infoMaximumActiveIndicatorsAdded": "Umeongeza idadi kubwa ya viashiria vya kazi.", + "infoAddSelectedIndicator": "Ongeza {indicator}", + "infoAddIndicator": "Ongeza kiashiria", + "labelDeleteAllIndicators": "Futa viashiria vyote", + "infoDeleteAllIndicators": "Hii itafuta viashiria vyote vya kazi.", + "labelDeleteIndicator": "Futa kiashiria cha {indicator}", + "infoDeleteIndicator": "Je! Una hakika unataka kufuta kiashiria hiki?", + "labelCancel": "Ghairi", + "labelDelete": "Futa", + "labelDeleteAll": "Futa Yote", + "infoUpto3indicatorsAllowed": "Hadi viashiria 3 vya kazi zinaruhusiwa.", + "infoNoActiveIndicators": "Huna viashiria vya kazi bado.", + "labelReset": "Weka upya", + "labelApply": "Tumia", + "labelOK": "SAWA", + "labelRSILine": "Mstari wa RSI", + "labelPeriod": "Kipindi", + "labelMinRange": "Kiwango cha chini", + "labelMaxRange": "Kiwango cha juu", + "labelSource": "chanzo", + "labelClose": "Kufunga", + "labelOpen": "Fungua", + "labelHigh": "Juu", + "labelLow": "Ndogo", + "labelHl/2": "Hl/2", + "labelHlc/3": "HLC/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Onyesha Maeneo", + "labelOverbought": "Kununua kupita kiasi", + "labelOversold": "Uuzwa kupita kiasi", + "labelMinSize": "Ukubwa wa chini", + "labelMaxSize": "Ukubwa wa juu", + "labelRange": "Mbalimbali", + "labelOverboughtLine": "Mstari wa kununuliwa kupita", + "labelOversoldLine": "Mstari uliouzwa zaidi", + "labelMACDLine": "Mstari wa MACD", + "labelFastMAPeriod": "Kipindi cha haraka cha MA", + "labelSlowMAPeriod": "Kipindi cha polepole cha MA", + "labelSignalLine": "Mstari wa ishara", + "labelSignalPeriod": "Kipindi cha ishara", + "labelIncreasingBar": "Kuongezeka kwa bar", + "labelDecreasingBar": "Baa ya kupungua", + "labelBollingerBandsTop": "Bollinger Bands juu", + "labelBollingerBandsMedian": "Bollinger Bands wastani", + "labelBollingerBandsBottom": "Bandi za Bollinger chini", + "labelChannelFill": "Kujaza kituo", + "labelFillColor": "Jaza rangi", + "labelStandardDeviations": "Upungufu wa kawaida", + "labelMovingAverageType": "Aina ya wastani ya kusonga", + "labelMALine": "Mstari wa MA", + "labelOffset": "Kidhibiti", + "labelType": "Aina", + "labelSimple": "Rahisi", + "labelExponential": "Mwanganyiko", + "labelWeighted": "Uzito", + "labelHull": "Hull", + "labelZeroLag": "Zero Lag", + "labelTimeSeries": "Mfululizo wa Wakati", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Tofauti", + "labelTriangular": "Pembetatu", + "label2Exponential": "2-Exponential", + "label3Exponential": "3-Mfanyiko" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_th.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_th.arb index dd7623f15..bb7761cd2 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_th.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_th.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "ตัวบ่งชี้" + "labelIndicators": "ตัวบ่งชี้", + "labelActive": "แอคทีฟ", + "labelAll": "ทั้งหมด", + "labelMomentum": "โมเมนตัม", + "labelVolatility": "ความผันผัน", + "labelMovingAverages": "ค่าเฉลี่ยเคลื่อนที่", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "ดัชนีความแข็งแรงสัมพัทธ์ (RSI)", + "labelRSI": "อาร์เอสไอ", + "labelBollingerBands": "โบลลิงเกอร์แบนด์ (BB)", + "labelBB": "บีบี", + "labelMovingAverage": "ค่าเฉลี่ยเคลื่อนที่ (MA)", + "labelMA": "แม่", + "infoMACD": "MACD เป็นตัวบ่งชี้การซื้อขายที่ใช้ในการวิเคราะห์ทางเทคนิคของราคาหุ้นมันควรจะเปิดเผยการเปลี่ยนแปลงในความแข็งแกร่งทิศทางโมเมนตัมและระยะเวลาของแนวโน้มในราคาหุ้น", + "infoRSI": "ดัชนีความแข็งแกร่งสัมพัทธ์ (RSI) เผยแพร่โดย เจ เวลเลส ไวลดอร์ราคาปัจจุบันเป็นปกติเป็นเปอร์เซ็นต์ระหว่าง 0 ถึง 100flutter_chart_id ของออสซิลเลเตอร์นี้ทำให้เข้าใจผิดเพราะไม่ได้เปรียบเทียบตราสารที่เกี่ยวข้องกับตราสารอื่น หรือชุดตราสารหนึ่ง แต่เป็นตัวแทนของราคาปัจจุบันเมื่อเทียบกับชิ้นส่วนล่าสุดอื่น ๆ ภายในความยาวหน้าต่างมองย้อนกลับที่เลือก", + "infoBB": "Bollinger Bands (BB) สามารถใช้เพื่อวัดความสูงหรือต่ำของราคาเมื่อเทียบกับการซื้อขายครั้งก่อน", + "infoMA": "ค่าเฉลี่ยเคลื่อนที่ (MA) ช่วยระบุแนวโน้มของตลาดโดยรวมโดยการกรองความผันผวนของราคาระยะสั้นการใช้ข้อมูลในอดีตจะคำนวณราคาเฉลี่ยในช่วงเวลาที่เฉพาะเจาะจงและแสดงเส้นบนแผนภูมิหากเส้น MA เคลื่อนไปขึ้นมันเป็นตัวบ่งชี้ของแนวโน้มขาขึ้น เทรนด์ขาลงหากเคลื่อนที่ลงลงสัญญาณการซื้อเกิดขึ้นเมื่อราคาเคลื่อนที่เหนือบรรทัด MA", + "infoMaximumActiveIndicatorsAdded": "คุณได้เพิ่มจำนวนตัวบ่งชี้ที่ใช้งานได้สูงสุดแล้ว", + "infoAddSelectedIndicator": "เพิ่ม {indicator}", + "infoAddIndicator": "เพิ่มตัวบ่งชี้", + "labelDeleteAllIndicators": "ลบตัวบ่งชี้ทั้งหมด", + "infoDeleteAllIndicators": "สิ่งนี้จะลบตัวบ่งชี้ที่ใช้งานอยู่ทั้งหมด", + "labelDeleteIndicator": "ลบตัวบ่งชี้ {indicator}", + "infoDeleteIndicator": "คุณแน่ใจหรือไม่ว่าต้องการลบตัวบ่งชี้นี้?", + "labelCancel": "ยกเลิก", + "labelDelete": "ลบ", + "labelDeleteAll": "ลบทั้งหมด", + "infoUpto3indicatorsAllowed": "อนุญาตให้ใช้ตัวบ่งชี้ที่ใช้งานได้สูงสุด 3 ตัว", + "infoNoActiveIndicators": "คุณยังไม่มีตัวบ่งชี้ที่ใช้งานอยู่", + "labelReset": "รีเซ็ต", + "labelApply": "สมัคร", + "labelOK": "โอเค", + "labelRSILine": "สาย RSI", + "labelPeriod": "ระยะเวลา", + "labelMinRange": "ช่วงขั้นต่ำ", + "labelMaxRange": "ช่วงสูงสุด", + "labelSource": "แหล่งที่มา", + "labelClose": "ปิด", + "labelOpen": "เปิด", + "labelHigh": "สูง", + "labelLow": "ต่ำ", + "labelHl/2": "เอชเอล/2", + "labelHlc/3": "เอชแอลซี/3", + "labelHlcc/4": "เอชลซีซี/4", + "labelOhlc/4": "โอเอลซี/4", + "labelShowZones": "แสดงโซน", + "labelOverbought": "ซื้อมากเกินไป", + "labelOversold": "ขายมากเกินไป", + "labelMinSize": "ขนาดขั้นต่ำ", + "labelMaxSize": "ขนาดสูงสุด", + "labelRange": "เรนจ์", + "labelOverboughtLine": "สายซื้อมากเกินไป", + "labelOversoldLine": "สายขายมากเกินไป", + "labelMACDLine": "สาย MACD", + "labelFastMAPeriod": "ระยะเวลา MA ที่รวดเร็ว", + "labelSlowMAPeriod": "ระยะเวลา MA ช้า", + "labelSignalLine": "สายสัญญาณ", + "labelSignalPeriod": "ระยะเวลาสัญญาณ", + "labelIncreasingBar": "แถบเพิ่มขึ้น", + "labelDecreasingBar": "แถบลดลง", + "labelBollingerBandsTop": "เสื้อแถบโบลลิงเจอร์", + "labelBollingerBandsMedian": "แถบโบลลิงเกอร์เฉลี่ย", + "labelBollingerBandsBottom": "แถบโบลลิงเกอร์ด้านล่าง", + "labelChannelFill": "เติมช่อง", + "labelFillColor": "เติมสี", + "labelStandardDeviations": "เบี่ยงเบนมาตรฐาน", + "labelMovingAverageType": "ประเภทค่าเฉลี่ยเคลื่อนที่", + "labelMALine": "สาย MA", + "labelOffset": "ออฟเซต", + "labelType": "ประเภท", + "labelSimple": "เรียบง่าย", + "labelExponential": "เลขชี้กำลัง", + "labelWeighted": "ถ่วงน้ำหนัก", + "labelHull": "ฮัลล์", + "labelZeroLag": "ความล่าช้าเป็นศูนย์", + "labelTimeSeries": "ซีรี่ส์เวลา", + "labelWellesWilder": "เวลเลส ไวล์เดอร์", + "labelVariable": "ตัวแปร", + "labelTriangular": "สามเหลี่ยม", + "label2Exponential": "2-เลขชี้กำลัง", + "label3Exponential": "3- เลขชี้กำลัง" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_tr.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_tr.arb index 0dc2ae764..2fac4eff4 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_tr.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_tr.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Göstergeler" + "labelIndicators": "Göstergeler", + "labelActive": "Aktif", + "labelAll": "Tümü", + "labelMomentum": "Momentum", + "labelVolatility": "Volatilite", + "labelMovingAverages": "Hareketli ortalamalar", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Göreceli Güç Endeksi (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Bollinger Bantları (BB)", + "labelBB": "BB", + "labelMovingAverage": "Hareketli Ortalama (MA)", + "labelMA": "MA", + "infoMACD": "MACD, hisse senedi fiyatlarının teknik analizinde kullanılan bir alım satım göstergesidir. Bir hisse senedinin fiyatındaki bir trendin gücü, yönü, momentumu ve süresindeki değişiklikleri ortaya çıkarması beklenir.", + "infoRSI": "Göreceli Güç Endeksi (RSI) J. Welles Wilder tarafından yayınlanmıştır. Mevcut fiyat 0 ile 100 arasında bir yüzde olarak normalleştirilir. Bu osilatörün flutter_chart_id'si yanıltıcıdır çünkü enstrümanı başka bir enstrümanla veya enstrüman setiyle karşılaştırmaz, bunun yerine seçilen geriye dönük pencere uzunluğu içindeki diğer son parçalara göre mevcut fiyatı temsil eder.", + "infoBB": "Bollinger Bantları (BB), önceki işlemlere göre fiyatın yüksekliğini veya düşüklüğünü ölçmek için kullanılabilir.", + "infoMA": "Hareketli Ortalama (MA), kısa vadeli fiyat dalgalanmalarını filtreleyerek genel piyasa trendini belirlemeye yardımcı olur. Geçmiş verileri kullanarak belirli bir dönemdeki ortalama fiyatı hesaplar ve grafik üzerinde bir çizgi çizer. MA çizgisi yukarı doğru hareket ederse, bu bir yükseliş trendinin, aşağı doğru hareket ederse bir düşüş trendinin göstergesidir. Fiyat MA çizgisinin üzerine çıktığında bir alım sinyali oluşur.", + "infoMaximumActiveIndicatorsAdded": "Maksimum sayıda aktif gösterge eklediniz.", + "infoAddSelectedIndicator": "{indicator}adresini ekleyin", + "infoAddIndicator": "Gösterge ekleyin", + "labelDeleteAllIndicators": "Tüm göstergeleri sil", + "infoDeleteAllIndicators": "Bu işlem tüm aktif göstergeleri silecektir.", + "labelDeleteIndicator": "Sil {indicator} göstergesi", + "infoDeleteIndicator": "Bu göstergeyi silmek istediğinizden emin misiniz?", + "labelCancel": "İptal", + "labelDelete": "Silme", + "labelDeleteAll": "Tümünü Sil", + "infoUpto3indicatorsAllowed": "En fazla 3 aktif göstergeye izin verilir.", + "infoNoActiveIndicators": "Henüz aktif göstergeniz yok.", + "labelReset": "Sıfırla", + "labelApply": "Başvurmak", + "labelOK": "TAMAM.", + "labelRSILine": "RSI çizgisi", + "labelPeriod": "Dönem", + "labelMinRange": "Min aralık", + "labelMaxRange": "Maksimum aralık", + "labelSource": "Kaynak", + "labelClose": "Kapat", + "labelOpen": "Açık", + "labelHigh": "Yüksek", + "labelLow": "Düşük", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Bölgeleri Göster", + "labelOverbought": "Aşırı alım", + "labelOversold": "Aşırı satım", + "labelMinSize": "Min boyut", + "labelMaxSize": "Maksimum boyut", + "labelRange": "Menzil", + "labelOverboughtLine": "Aşırı alım çizgisi", + "labelOversoldLine": "Aşırı satım çizgisi", + "labelMACDLine": "MACD çizgisi", + "labelFastMAPeriod": "Hızlı MA dönemi", + "labelSlowMAPeriod": "Yavaş MA dönemi", + "labelSignalLine": "Sinyal hattı", + "labelSignalPeriod": "Sinyal süresi", + "labelIncreasingBar": "Artan çubuk", + "labelDecreasingBar": "Azalan çubuk", + "labelBollingerBandsTop": "Bollinger Bantları üst", + "labelBollingerBandsMedian": "Bollinger Bantları medyan", + "labelBollingerBandsBottom": "Bollinger Bantları alt", + "labelChannelFill": "Kanal dolgusu", + "labelFillColor": "Dolgu rengi", + "labelStandardDeviations": "Standart sapmalar", + "labelMovingAverageType": "Hareketli Ortalama Türü", + "labelMALine": "Ana hat", + "labelOffset": "Ofset", + "labelType": "Tip", + "labelSimple": "Basit", + "labelExponential": "Üstel", + "labelWeighted": "Ağırlıklı", + "labelHull": "Gövde", + "labelZeroLag": "Sıfır Gecikme", + "labelTimeSeries": "Zaman Serisi", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Değişken", + "labelTriangular": "Üçgen", + "label2Exponential": "2-Eksponansiyel", + "label3Exponential": "3-Eksponansiyel" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_vi.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_vi.arb index f6ce868bf..558ae33ba 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_vi.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_vi.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "Các chỉ số" + "labelIndicators": "Các chỉ số", + "labelActive": "Hoạt động", + "labelAll": "Tất cả", + "labelMomentum": "Đà", + "labelVolatility": "Có trọng lượng", + "labelMovingAverages": "Đường trung bình động", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "Chỉ số sức mạnh tương đối (RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "Dải Bollinger (BB)", + "labelBB": "BB", + "labelMovingAverage": "Đường trung bình động (MA)", + "labelMA": "MA", + "infoMACD": "MACD là một chỉ báo giao dịch được sử dụng trong phân tích kỹ thuật giá cổ phiếu. Nó được cho là tiết lộ những thay đổi về sức mạnh, hướng, đà và thời gian của xu hướng trong giá cổ phiếu.", + "infoRSI": "Chỉ số sức mạnh tương đối (RSI) được công bố bởi J. Welles Wilder. Giá hiện tại được chuẩn hóa theo tỷ lệ phần trăm từ 0 đến 100. Flutter_chart_id của bộ dao động này gây hiểu nhầm vì nó không so sánh công cụ so với một công cụ hoặc bộ công cụ khác, mà đại diện cho giá hiện tại so với các phần gần đây khác trong độ dài cửa sổ nhìn lại đã chọn.", + "infoBB": "Dải Bollinger (BB) có thể được sử dụng để đo mức cao hoặc thấp của giá so với các giao dịch trước đó.", + "infoMA": "Đường trung bình động (MA) giúp xác định xu hướng thị trường tổng thể bằng cách lọc ra các biến động giá ngắn hạn. Sử dụng dữ liệu lịch sử, nó tính toán giá trung bình trong một khoảng thời gian cụ thể và vẽ một đường trên biểu đồ. Nếu đường MA di chuyển lên, đó là một chỉ báo của xu hướng tăng, xu hướng giảm nếu nó di chuyển xuống. Tín hiệu mua xảy ra khi giá di chuyển trên đường MA.", + "infoMaximumActiveIndicatorsAdded": "Bạn đã thêm số lượng chỉ báo hoạt động tối đa.", + "infoAddSelectedIndicator": "Thêm {indicator}", + "infoAddIndicator": "Thêm chỉ báo", + "labelDeleteAllIndicators": "Xóa tất cả các chỉ số", + "infoDeleteAllIndicators": "Điều này sẽ xóa tất cả các chỉ số hoạt động.", + "labelDeleteIndicator": "Xóa chỉ báo {indicator}", + "infoDeleteIndicator": "Bạn có chắc chắn muốn xóa chỉ báo này không?", + "labelCancel": "Hủy", + "labelDelete": "Xóa", + "labelDeleteAll": "Xóa tất cả", + "infoUpto3indicatorsAllowed": "Cho phép tối đa 3 chỉ số hoạt động.", + "infoNoActiveIndicators": "Bạn chưa có chỉ số hoạt động.", + "labelReset": "Đặt lại", + "labelApply": "Áp dụng", + "labelOK": "ĐƯỢC", + "labelRSILine": "Dòng RSI", + "labelPeriod": "Thời kỳ", + "labelMinRange": "Phạm vi tối thiểu", + "labelMaxRange": "Phạm vi tối đa", + "labelSource": "Nguồn", + "labelClose": "Đóng", + "labelOpen": "Mở", + "labelHigh": "Cao", + "labelLow": "Thấp", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "Hiển thị khu vực", + "labelOverbought": "Mua quá mức", + "labelOversold": "Bán quá mức", + "labelMinSize": "Kích thước tối thiểu", + "labelMaxSize": "Kích thước tối đa", + "labelRange": "Phạm vi", + "labelOverboughtLine": "Dòng quá mua", + "labelOversoldLine": "Dòng bán quá mức", + "labelMACDLine": "Dòng MACD", + "labelFastMAPeriod": "Thời gian MA nhanh", + "labelSlowMAPeriod": "Thời gian MA chậm", + "labelSignalLine": "Đường tín hiệu", + "labelSignalPeriod": "Thời gian tín hiệu", + "labelIncreasingBar": "Tăng thanh", + "labelDecreasingBar": "Thanh giảm", + "labelBollingerBandsTop": "Bollinger Bands hàng đầu", + "labelBollingerBandsMedian": "Dải Bollinger trung bình", + "labelBollingerBandsBottom": "Dải Bollinger phía dưới", + "labelChannelFill": "Điền kênh", + "labelFillColor": "Tô màu", + "labelStandardDeviations": "Độ lệch chuẩn", + "labelMovingAverageType": "Loại trung bình di chuyển", + "labelMALine": "Dòng MA", + "labelOffset": "Bù đắp", + "labelType": "Kiểu", + "labelSimple": "Đơn giản", + "labelExponential": "Theo cấp số nhân", + "labelWeighted": "Có trọng số", + "labelHull": "Thân tàu", + "labelZeroLag": "Không có độ trễ", + "labelTimeSeries": "Chuỗi thời gian", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "Biến", + "labelTriangular": "Tam giác", + "label2Exponential": "2-cấp số nhân", + "label3Exponential": "3-cấp số nhân" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_zh.arb b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_zh.arb index 4704206cc..e99048b37 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_zh.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_mobile_chart_wrapper/app_zh.arb @@ -1,3 +1,83 @@ { - "labelIndicators": "指標" + "labelIndicators": "指標", + "labelActive": "活躍", + "labelAll": "全部", + "labelMomentum": "動量", + "labelVolatility": "波動性", + "labelMovingAverages": "移動平均線", + "labelMACD": "MACD", + "labelRelativeStrengthIndex": "相對強度指數(RSI)", + "labelRSI": "RSI", + "labelBollingerBands": "布林格帶(BB)", + "labelBB": "BB", + "labelMovingAverage": "移動平均值 (MA)", + "labelMA": "MA", + "infoMACD": "MACD 是交易指標,用於股票價格的技術分析。可顯示股票價格中趨勢的強度、方向、動量和持續時間的變化。", + "infoRSI": "相對強度指數(RSI)由 J. Welles Wilder 發布。將目前價格以 0 到 100 之間的百分比標準化。此振盪器的 flutter_chart_id 具有誤導性,因為它不與其他工具或一組工具相比較,而是代表所選回顧窗口長度內與其他最近的股票相對的目前價格。", + "infoBB": "布林格帶(BB)可用於測量與之前交易相對於價格的高度或低度。", + "infoMA": "移動平均線(MA)通過過濾短期價格波動來幫助識別整體市場趨勢。它使用歷史資料,計算特定期間的平均價格,並在圖表繪線。如果 MA 線向上移動,則是上升趨勢的指標,如果向下移動則是下降趨勢的指標。當價格走在 MA 線上方時,就會出現買入信號。", + "infoMaximumActiveIndicatorsAdded": "已新增使用中指標數目上限。", + "infoAddSelectedIndicator": "新增 {indicator}", + "infoAddIndicator": "新增指標", + "labelDeleteAllIndicators": "刪除所有指標", + "infoDeleteAllIndicators": "這將刪除所有活躍指標。", + "labelDeleteIndicator": "刪除 {indicator} 指標", + "infoDeleteIndicator": "確定要刪除此指標嗎?", + "labelCancel": "取消", + "labelDelete": "刪除", + "labelDeleteAll": "刪除全部", + "infoUpto3indicatorsAllowed": "最多允許 3 個活躍指標。", + "infoNoActiveIndicators": "尚未有活躍指標。", + "labelReset": "重設", + "labelApply": "申請", + "labelOK": "好", + "labelRSILine": "RSI 線", + "labelPeriod": "週期", + "labelMinRange": "最小範圍", + "labelMaxRange": "最大範圍", + "labelSource": "來源", + "labelClose": "關閉", + "labelOpen": "開啟", + "labelHigh": "High", + "labelLow": "Low", + "labelHl/2": "Hl/2", + "labelHlc/3": "Hlc/3", + "labelHlcc/4": "Hlcc/4", + "labelOhlc/4": "Ohlc/4", + "labelShowZones": "顯示區域", + "labelOverbought": "超買", + "labelOversold": "超賣", + "labelMinSize": "最小尺寸", + "labelMaxSize": "最大尺寸", + "labelRange": "範圍", + "labelOverboughtLine": "超買線", + "labelOversoldLine": "超賣線", + "labelMACDLine": "MACD 線", + "labelFastMAPeriod": "快速 MA 週期", + "labelSlowMAPeriod": "慢速 MA 週期", + "labelSignalLine": "信號線", + "labelSignalPeriod": "信號週期", + "labelIncreasingBar": "增加條型線", + "labelDecreasingBar": "減少條型線", + "labelBollingerBandsTop": "布林格帶頂部", + "labelBollingerBandsMedian": "布林格帶中位數", + "labelBollingerBandsBottom": "布林格帶底部", + "labelChannelFill": "通道填充", + "labelFillColor": "填色", + "labelStandardDeviations": "標準偏差", + "labelMovingAverageType": "移動平均線類型", + "labelMALine": "MA 線", + "labelOffset": "偏移", + "labelType": "類型", + "labelSimple": "簡單", + "labelExponential": "指數式", + "labelWeighted": "加權", + "labelHull": "Hull", + "labelZeroLag": "零延遲", + "labelTimeSeries": "時間序列", + "labelWellesWilder": "Welles Wilder", + "labelVariable": "變量", + "labelTriangular": "三角形", + "label2Exponential": "2-指數式", + "label3Exponential": "3-指數式" } \ No newline at end of file diff --git a/packages/deriv_localizations/lib/l10n/deriv_passkeys/app_de.arb b/packages/deriv_localizations/lib/l10n/deriv_passkeys/app_de.arb index 089fdada3..8531e26ed 100644 --- a/packages/deriv_localizations/lib/l10n/deriv_passkeys/app_de.arb +++ b/packages/deriv_localizations/lib/l10n/deriv_passkeys/app_de.arb @@ -28,7 +28,7 @@ "howToCreatePasskeyDescription2": "Sie können einen Passkey pro Gerät erstellen.", "p2pHowToCreatePasskey": "Wie erstelle ich einen Passkey?", "p2pHowToCreatePasskeyDescription1": "Gehen Sie in Ihrer Deriv P2P-App zu „Profil“.", - "p2pHowToCreatePasskeyDescription2": "Tippen Sie auf „Hauptschlüssel“, um Ihren Hauptschlüssel zu erstellen.", + "p2pHowToCreatePasskeyDescription2": "Tippen Sie auf „Passkeys“, um Ihren Passkey zu erstellen.", "whereArePasskeysSaved": "Wo werden die Passkeys gespeichert?", "whereArePasskeysSavedDescriptionAndroid": "Android: Google Passwort-Manager.", "whereArePasskeysSavedDescriptionIOS": "iOS: iCloud-Schlüsselbund.", diff --git a/packages/deriv_mobile_chart_wrapper/CHANGELOG.md b/packages/deriv_mobile_chart_wrapper/CHANGELOG.md index 021636ca8..0323f0d7c 100644 --- a/packages/deriv_mobile_chart_wrapper/CHANGELOG.md +++ b/packages/deriv_mobile_chart_wrapper/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.0.2+3 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 0.0.2+2 + + - Update a dependency to the latest release. + ## 0.0.2+1 - **FIX**(deriv_mobile_chart_wrapper): update readme file ([#672](https://github.com/regentmarkets/flutter-deriv-packages/issues/672)). ([13e6b3f3](https://github.com/regentmarkets/flutter-deriv-packages/commit/13e6b3f35ba863098fd9785daaa8ccc7cb23b388)) diff --git a/packages/deriv_mobile_chart_wrapper/lib/src/mobile_tools_ui/colours_palettes.dart b/packages/deriv_mobile_chart_wrapper/lib/src/mobile_tools_ui/colours_palettes.dart new file mode 100644 index 000000000..f368f247f --- /dev/null +++ b/packages/deriv_mobile_chart_wrapper/lib/src/mobile_tools_ui/colours_palettes.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class ColoursPalettes extends StatefulWidget { + final ValueChanged onColorSelected; + + const ColoursPalettes({super.key, required this.onColorSelected}); + + @override + ColoursPalettesState createState() => ColoursPalettesState(); +} + +class ColoursPalettesState extends State { + final List colors = [ + const Color(0xFFFFFFFF), // White + const Color(0xFFF39230), // Orange + const Color(0xFFEF6B53), // Deep Orange + const Color(0xFFD73737), // Red + const Color(0xFF03BFF0), // Light Blue + const Color(0xFF3271B4), // Blue + const Color(0xFF2FBCB5), // Teal + const Color(0xFF8EC648), // Light Green + const Color(0xFF48A25C), // Green + const Color(0xFFFFF224), // Yellow + const Color(0xFFEE6EA9), // Pink + const Color(0xFF853289), // Purple + ]; + + final Color borderColor = const Color(0xFF85ACB0); + Color? selectedColor; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(20.0), + child: GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 6, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + ), + itemCount: colors.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + setState(() { + selectedColor = colors[index]; + }); + widget.onColorSelected(colors[index]); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: selectedColor == colors[index] + ? Border.all(color: borderColor, width: 1) + : null, + ), + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Container( + decoration: BoxDecoration( + color: colors[index], + borderRadius: BorderRadius.circular(4), + ), + ), + ), + ), + ); + }, + ), + ); + } +} diff --git a/packages/deriv_mobile_chart_wrapper/pubspec.yaml b/packages/deriv_mobile_chart_wrapper/pubspec.yaml index 2770f16ac..582459a89 100644 --- a/packages/deriv_mobile_chart_wrapper/pubspec.yaml +++ b/packages/deriv_mobile_chart_wrapper/pubspec.yaml @@ -1,6 +1,6 @@ name: deriv_mobile_chart_wrapper description: A new Flutter package project. -version: 0.0.2+1 +version: 0.0.2+3 homepage: environment: @@ -31,7 +31,7 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 provider: ^6.0.5 flutter_svg: ^2.0.9 diff --git a/packages/deriv_passkeys/CHANGELOG.md b/packages/deriv_passkeys/CHANGELOG.md index ff47fd72f..18d4afa6a 100644 --- a/packages/deriv_passkeys/CHANGELOG.md +++ b/packages/deriv_passkeys/CHANGELOG.md @@ -1,3 +1,27 @@ +## 0.0.3+5 + + - **REFACTOR**(version): updated the version of flutter deriv api ([#694](https://github.com/regentmarkets/flutter-deriv-packages/issues/694)). ([eac7e8cb](https://github.com/regentmarkets/flutter-deriv-packages/commit/eac7e8cba4e9310d30296e07a47731f08d4d7342)) + +## 0.0.3+4 + + - **FIX**(deriv_passkeys): fix some missing keys in passkey login page ([#692](https://github.com/regentmarkets/flutter-deriv-packages/issues/692)). ([d944a1c3](https://github.com/regentmarkets/flutter-deriv-packages/commit/d944a1c37f127f35143d9920532f76bc3487ebd4)) + +## 0.0.3+3 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 0.0.3+2 + + - Update a dependency to the latest release. + +## 0.0.3+1 + + - **FIX**(deriv_passkeys): add keys to passkey login page ([#676](https://github.com/regentmarkets/flutter-deriv-packages/issues/676)). ([aa84a46d](https://github.com/regentmarkets/flutter-deriv-packages/commit/aa84a46dfb9cd22a335276c1ae0063ffee7852ef)) + +## 0.0.3 + + - **FEAT**(deriv_passkeys): [P2PS-3072] add keys to deriv passkey package effortless passkeys login page ([#677](https://github.com/regentmarkets/flutter-deriv-packages/issues/677)). ([39472704](https://github.com/regentmarkets/flutter-deriv-packages/commit/39472704a3d264bc5f64ba2ae75e29134f890590)) + ## 0.0.2+9 - **REFACTOR**(deriv_passkeys): update deriv api dependency ([#656](https://github.com/regentmarkets/flutter-deriv-packages/issues/656)). ([3425078b](https://github.com/regentmarkets/flutter-deriv-packages/commit/3425078b52baac4f387504c9d41063bda1dba249)) diff --git a/packages/deriv_passkeys/lib/src/presentation/pages/effortless_passkeys_login_page.dart b/packages/deriv_passkeys/lib/src/presentation/pages/effortless_passkeys_login_page.dart index 7fd1f0f51..4e097b3d9 100644 --- a/packages/deriv_passkeys/lib/src/presentation/pages/effortless_passkeys_login_page.dart +++ b/packages/deriv_passkeys/lib/src/presentation/pages/effortless_passkeys_login_page.dart @@ -21,6 +21,7 @@ class EffortlessPasskeysPage extends StatelessWidget required this.onPageClosed, required this.addMorePasskeysNavigationCallback, required this.continueTradingNavigationCallback, + this.effortlessPasskeysPageKeys, super.key, }) { trackOpenEffortlessLoginPage(); @@ -38,6 +39,9 @@ class EffortlessPasskeysPage extends StatelessWidget /// Callback to be called when the flow is complete. final void Function(BuildContext context) onPageClosed; + /// Pass an object of keys to assign to specific widget in this page. + final EffortlessPasskeysPageKeys? effortlessPasskeysPageKeys; + @override Widget build(BuildContext context) => WillPopScope( onWillPop: () async { @@ -99,6 +103,8 @@ class EffortlessPasskeysPage extends StatelessWidget context.derivPasskeysLocalizations .maybeLater .toUpperCase(), + key: effortlessPasskeysPageKeys + ?.maybeLaterTextButtonKey, style: TextStyle( color: context.theme.colors.coral, ), @@ -121,6 +127,8 @@ class EffortlessPasskeysPage extends StatelessWidget Text( context.derivPasskeysLocalizations .effortlessLoginWithPasskeys, + key: effortlessPasskeysPageKeys + ?.loginWithPasskeyTextKey, style: const TextStyle(fontSize: 20), ), const SizedBox( @@ -131,6 +139,8 @@ class EffortlessPasskeysPage extends StatelessWidget text: context .derivPasskeysLocalizations .noNeedToRememberPassword, + textKey: effortlessPasskeysPageKeys + ?.noNeedToRememberPasswordRowKey, ), Divider( color: context.theme.colors.hover, @@ -140,6 +150,8 @@ class EffortlessPasskeysPage extends StatelessWidget text: context .derivPasskeysLocalizations .syncAcrossDevices, + textKey: effortlessPasskeysPageKeys + ?.syncAcrossDevicesRowKey, ), Divider( color: context.theme.colors.hover, @@ -149,6 +161,8 @@ class EffortlessPasskeysPage extends StatelessWidget text: context .derivPasskeysLocalizations .useYourBiometrics, + textKey: effortlessPasskeysPageKeys + ?.useBiometricsRowKey, ), Divider( color: context.theme.colors.hover, @@ -170,6 +184,8 @@ class EffortlessPasskeysPage extends StatelessWidget PlaceholderAlignment .middle, child: InkWell( + key: effortlessPasskeysPageKeys + ?.hyperlinkInkWellKey, onTap: () { Navigator.push( context, @@ -202,6 +218,9 @@ class EffortlessPasskeysPage extends StatelessWidget style: TextStyle( color: context.theme .colors.coral), + key: + effortlessPasskeysPageKeys + ?.hereRichTextKey, ), ), ), @@ -226,6 +245,8 @@ class EffortlessPasskeysPage extends StatelessWidget child: Text( context.derivPasskeysLocalizations .createPasskey, + key: effortlessPasskeysPageKeys + ?.createPasskeyButtonKey, style: TextStyle( color: context.theme.colors.prominent, ), @@ -243,3 +264,42 @@ class EffortlessPasskeysPage extends StatelessWidget ), ); } + +/// A class that allows users to pass keys to [EffortlessPasskeysPage]. +class EffortlessPasskeysPageKeys { + /// Constructs [EffortlessPasskeysPageKeys]. + EffortlessPasskeysPageKeys({ + this.createPasskeyButtonKey, + this.hyperlinkInkWellKey, + this.maybeLaterTextButtonKey, + this.loginWithPasskeyTextKey, + this.noNeedToRememberPasswordRowKey, + this.syncAcrossDevicesRowKey, + this.useBiometricsRowKey, + this.hereRichTextKey, + }); + + /// Key for create passkey button widget. + final Key? createPasskeyButtonKey; + + /// Key for hyper link ink well widget. + final Key? hyperlinkInkWellKey; + + /// Key for maybe later text button widget. + final Key? maybeLaterTextButtonKey; + + /// Key for login with passkey text widget. + final Key? loginWithPasskeyTextKey; + + /// Key for no need to remember password row widget. + final Key? noNeedToRememberPasswordRowKey; + + /// Key for sync across devices row widget. + final Key? syncAcrossDevicesRowKey; + + /// Key for use biometrics row widget. + final Key? useBiometricsRowKey; + + /// Key for here rich text widget. + final Key? hereRichTextKey; +} diff --git a/packages/deriv_passkeys/lib/src/presentation/widgets/icon_text_row_widget.dart b/packages/deriv_passkeys/lib/src/presentation/widgets/icon_text_row_widget.dart index b412b7d23..595290de8 100644 --- a/packages/deriv_passkeys/lib/src/presentation/widgets/icon_text_row_widget.dart +++ b/packages/deriv_passkeys/lib/src/presentation/widgets/icon_text_row_widget.dart @@ -7,6 +7,7 @@ class IconTextRowWidget extends StatelessWidget { const IconTextRowWidget({ required this.assetName, required this.text, + this.textKey, }); /// The name of the asset to display. @@ -15,6 +16,9 @@ class IconTextRowWidget extends StatelessWidget { /// The text to display. final String text; + /// Key for text value + final Key? textKey; + @override Widget build(BuildContext context) => Row( children: [ @@ -23,7 +27,7 @@ class IconTextRowWidget extends StatelessWidget { package: 'deriv_passkeys', ), const SizedBox(width: 8), - Expanded(child: Text(text)), + Expanded(child: Text(text, key: textKey)), ], ); } diff --git a/packages/deriv_passkeys/pubspec.yaml b/packages/deriv_passkeys/pubspec.yaml index b8c734770..bc67652da 100644 --- a/packages/deriv_passkeys/pubspec.yaml +++ b/packages/deriv_passkeys/pubspec.yaml @@ -1,6 +1,6 @@ name: deriv_passkeys description: Deriv Passkeys Flutter Plugin -version: 0.0.2+9 +version: 0.0.3+5 publish_to: "none" environment: @@ -32,7 +32,7 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 deriv_http_client: git: @@ -43,7 +43,7 @@ dependencies: flutter_deriv_api: git: url: git@github.com:deriv-com/flutter-deriv-api.git - ref: v1.0.0 + ref: v1.1.0 flutter_svg: ^2.0.9 plugin_platform_interface: ^2.0.2 diff --git a/packages/deriv_ui/CHANGELOG.md b/packages/deriv_ui/CHANGELOG.md index 84203b2c2..ae7fb41da 100644 --- a/packages/deriv_ui/CHANGELOG.md +++ b/packages/deriv_ui/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.0.8+1 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 0.0.8 + + - **FEAT**(deriv_ui): [DERG 2450] Added Timeline Widget to Deriv UI ([#631](https://github.com/regentmarkets/flutter-deriv-packages/issues/631)). ([e34d78b3](https://github.com/regentmarkets/flutter-deriv-packages/commit/e34d78b303358cb5f91abab14a2a042ce3650b0f)) + ## 0.0.7+9 - Update a dependency to the latest release. diff --git a/packages/deriv_ui/lib/components/timeline/src/connector_theme.dart b/packages/deriv_ui/lib/components/timeline/src/connector_theme.dart new file mode 100644 index 000000000..2209db96a --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/connector_theme.dart @@ -0,0 +1,203 @@ +import 'dart:ui' show lerpDouble; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'connectors.dart'; +import 'timeline_node.dart'; +import 'timeline_theme.dart'; + +/// Defines the visual properties of [SolidLineConnector], connectors inside +/// [TimelineNode]. +/// +/// Descendant widgets obtain the current [ConnectorThemeData] object using +/// `ConnectorTheme.of(context)`. Instances of [ConnectorThemeData] can be +/// customized with [ConnectorThemeData.copyWith]. +/// +/// Typically a [ConnectorThemeData] is specified as part of the overall +/// [TimelineTheme] with [TimelineThemeData.connectorTheme]. +/// +/// All [ConnectorThemeData] properties are `null` by default. When null, the +/// widgets will provide their own defaults. +/// +/// See also: +/// +/// * [TimelineThemeData], which describes the overall theme information for +/// the timeline. +@immutable +class ConnectorThemeData with Diagnosticable { + /// Creates a theme that can be used for [ConnectorTheme] or + /// [TimelineThemeData.connectorTheme]. + const ConnectorThemeData({ + this.color, + this.space, + this.thickness, + this.indent, + }); + + /// The color of [SolidLineConnector]s and connectors inside [TimelineNode]s, + /// and so forth. + final Color? color; + + /// This represents the amount of horizontal or vertical space the connector + /// takes up. + final double? space; + + /// The thickness of the line drawn within the connector. + final double? thickness; + + /// The amount of empty space at the edge of [SolidLineConnector]. + final double? indent; + + /// Creates a copy of this object with the given fields replaced with the new + /// values. + ConnectorThemeData copyWith({ + Color? color, + double? space, + double? thickness, + double? indent, + }) => + ConnectorThemeData( + color: color ?? this.color, + space: space ?? this.space, + thickness: thickness ?? this.thickness, + indent: indent ?? this.indent, + ); + + /// Linearly interpolate between two Connector themes. + /// + /// The argument `t` must not be null. + /// + /// {@macro dart.ui.shadow.lerp} + static ConnectorThemeData lerp( + ConnectorThemeData? a, ConnectorThemeData? b, double t) => + ConnectorThemeData( + color: Color.lerp(a?.color, b?.color, t), + space: lerpDouble(a?.space, b?.space, t), + thickness: lerpDouble(a?.thickness, b?.thickness, t), + indent: lerpDouble(a?.indent, b?.indent, t), + ); + + @override + int get hashCode => Object.hash( + color, + space, + thickness, + indent, + ); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is ConnectorThemeData && + other.color == color && + other.space == space && + other.thickness == thickness && + other.indent == indent; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ColorProperty('color', color, defaultValue: null)) + ..add(DoubleProperty('space', space, defaultValue: null)) + ..add(DoubleProperty('thickness', thickness, defaultValue: null)) + ..add(DoubleProperty('indent', indent, defaultValue: null)); + } +} + +/// An inherited widget that defines the configuration for +/// [SolidLineConnector]s, connectors inside [TimelineNode]s. +class ConnectorTheme extends InheritedTheme { + /// Creates a connector theme that controls the configurations for + /// [SolidLineConnector]s, connectors inside [TimelineNode]s. + const ConnectorTheme({ + required this.data, + required Widget child, + Key? key, + }) : super(key: key, child: child); + + /// The properties for descendant [SolidLineConnector]s, connectors inside + /// [TimelineNode]s. + final ConnectorThemeData data; + + /// The closest instance of this class's [data] value that encloses the given + /// context. + /// + /// If there is no ancestor, it returns [TimelineThemeData.connectorTheme]. + /// Applications can assume that the returned value will not be null. + /// + /// Typical usage is as follows: + /// + /// ```dart + /// ConnectorThemeData theme = ConnectorTheme.of(context); + /// ``` + static ConnectorThemeData of(BuildContext context) { + final ConnectorTheme? connectorTheme = + context.dependOnInheritedWidgetOfExactType(); + return connectorTheme?.data ?? TimelineTheme.of(context).connectorTheme; + } + + @override + Widget wrap(BuildContext context, Widget child) { + final ConnectorTheme? ancestorTheme = + context.findAncestorWidgetOfExactType(); + return identical(this, ancestorTheme) + ? child + : ConnectorTheme(data: data, child: child); + } + + @override + bool updateShouldNotify(ConnectorTheme oldWidget) => data != oldWidget.data; + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + data.debugFillProperties(properties); + } +} + +/// Connector component configured through [ConnectorTheme] +mixin ThemedConnectorComponent on Widget { + /// {@template timelines.connector.direction} + /// If this is null, then the [TimelineThemeData.direction] is used. + /// {@endtemplate} + Axis? get direction; + Axis getEffectiveDirection(BuildContext context) => + direction ?? TimelineTheme.of(context).direction; + + /// {@template timelines.connector.thickness} + /// If this is null, then the [ConnectorThemeData.thickness] is used which + /// defaults to 2.0. + /// {@endtemplate} + double? get thickness; + double getEffectiveThickness(BuildContext context) => + thickness ?? ConnectorTheme.of(context).thickness ?? 2.0; + + /// {@template timelines.connector.space} + /// If this is null, then the [ConnectorThemeData.space] is used. If that is + /// also null, then this defaults to double.infinity. + /// {@endtemplate} + double? get space; + double? getEffectiveSpace(BuildContext context) => + space ?? ConnectorTheme.of(context).space; + + double? get indent; + double getEffectiveIndent(BuildContext context) => + indent ?? ConnectorTheme.of(context).indent ?? 0.0; + + double? get endIndent; + double getEffectiveEndIndent(BuildContext context) => + endIndent ?? ConnectorTheme.of(context).indent ?? 0.0; + + Color? get color; + Color getEffectiveColor(BuildContext context) => + color ?? + ConnectorTheme.of(context).color ?? + TimelineTheme.of(context).color; +} diff --git a/packages/deriv_ui/lib/components/timeline/src/connectors.dart b/packages/deriv_ui/lib/components/timeline/src/connectors.dart new file mode 100644 index 000000000..809b7b1c5 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/connectors.dart @@ -0,0 +1,445 @@ +import 'package:flutter/material.dart'; +import 'connector_theme.dart'; +import 'line_painter.dart'; +import 'timelines.dart'; +import 'timeline_node.dart'; +import 'timeline_theme.dart'; + +/// Abstract class for predefined connector widgets. +/// +/// See also: +/// +/// * [SolidLineConnector], which is a [Connector] that draws solid line. +/// * [DashedLineConnector], which is a [Connector] that draws outlined dot. +/// * [TransparentConnector], which is a [Connector] that only takes up space. +abstract class Connector extends StatelessWidget with ThemedConnectorComponent { + /// Creates an connector. + const Connector({ + Key? key, + this.direction, + this.space, + this.thickness, + this.indent, + this.endIndent, + this.color, + }) : assert(thickness == null || thickness >= 0.0), + assert(space == null || space >= 0.0), + assert(indent == null || indent >= 0.0), + assert(endIndent == null || endIndent >= 0.0), + super(key: key); + + /// Creates a solid line connector. + /// + /// See also: + /// + /// * [SolidLineConnector], exactly the same. + factory Connector.solidLine({ + Key? key, + Axis? direction, + double? thickness, + double? space, + double? indent, + double? endIndent, + Color? color, + }) => + SolidLineConnector( + key: key, + direction: direction, + thickness: thickness, + space: space, + indent: indent, + endIndent: endIndent, + color: color, + ); + + /// Creates a dashed line connector. + /// + /// See also: + /// + /// * [DashedLineConnector], exactly the same. + factory Connector.dashedLine({ + Key? key, + Axis? direction, + double? thickness, + double? dash, + double? gap, + double? space, + double? indent, + double? endIndent, + Color? color, + Color? gapColor, + }) => + DashedLineConnector( + key: key, + direction: direction, + thickness: thickness, + dash: dash, + gap: gap, + space: space, + indent: indent, + endIndent: endIndent, + color: color, + gapColor: gapColor, + ); + + /// Creates a dashed transparent connector. + /// + /// See also: + /// + /// * [TransparentConnector], exactly the same. + factory Connector.transparent({ + Key? key, + Axis? direction, + double? indent, + double? endIndent, + double? space, + }) => + TransparentConnector( + key: key, + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + ); + + /// {@macro timelines.direction} + /// + /// {@macro timelines.connector.direction} + @override + final Axis? direction; + + /// The connector's cross axis size extent. + /// + /// The connector itself is always drawn as a line that is centered within the + /// size specified by this value. + /// {@macro timelines.connector.space} + @override + final double? space; + + /// The thickness of the line drawn within the connector. + /// + /// {@macro timelines.connector.thickness} + @override + final double? thickness; + + /// The amount of empty space to the leading edge of the connector. + /// + /// If this is null, then the [ConnectorThemeData.indent] is used. If that is + /// also null, then this defaults to 0.0. + @override + final double? indent; + + /// The amount of empty space to the trailing edge of the connector. + /// + /// If this is null, then the [ConnectorThemeData.indent] is used. If that is + /// also null, then this defaults to 0.0. + @override + final double? endIndent; + + /// The color to use when painting the line. + /// + /// If this is null, then the [ConnectorThemeData.color] is used. If that is + /// also null, then [TimelineThemeData.color] is used. + @override + final Color? color; +} + +/// A thin line, with padding on either side. +/// +/// The box's total cross axis size(width or height, depend on [direction]) is +/// controlled by [space]. +/// +/// The appropriate padding is automatically computed from the cross axis size. +class SolidLineConnector extends Connector { + /// Creates a solid line connector. + /// + /// The [thickness], [space], [indent], and [endIndent] must be null or + /// non-negative. + const SolidLineConnector({ + Key? key, + Axis? direction, + double? thickness, + double? space, + double? indent, + double? endIndent, + Color? color, + }) : super( + key: key, + direction: direction, + thickness: thickness, + space: space, + indent: indent, + endIndent: endIndent, + color: color, + ); + + @override + Widget build(BuildContext context) { + final Axis direction = getEffectiveDirection(context); + final double thickness = getEffectiveThickness(context); + final Color color = getEffectiveColor(context); + final double? space = getEffectiveSpace(context); + final double indent = getEffectiveIndent(context); + final double endIndent = getEffectiveEndIndent(context); + + switch (direction) { + case Axis.vertical: + return _ConnectorIndent( + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + child: Container( + width: thickness, + color: color, + ), + ); + case Axis.horizontal: + return _ConnectorIndent( + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + child: Container( + height: thickness, + color: color, + ), + ); + } + } +} + +/// A decorated thin line, with padding on either side. +/// +/// The box's total cross axis size(width or height, depend on [direction]) is +/// controlled by [space]. +/// +/// The appropriate padding is automatically computed from the cross axis size. +class DecoratedLineConnector extends Connector { + /// Creates a decorated line connector. + /// + /// The [thickness], [space], [indent], and [endIndent] must be null or + /// non-negative. + const DecoratedLineConnector({ + Key? key, + Axis? direction, + double? thickness, + double? space, + double? indent, + double? endIndent, + this.decoration, + }) : super( + key: key, + direction: direction, + thickness: thickness, + space: space, + indent: indent, + endIndent: endIndent, + ); + + /// The decoration to paint line. + /// + /// Use the [SolidLineConnector] class to specify a simple solid color line. + final Decoration? decoration; + + @override + Widget build(BuildContext context) { + final Axis direction = getEffectiveDirection(context); + final double thickness = getEffectiveThickness(context); + final double? space = getEffectiveSpace(context); + final double indent = getEffectiveIndent(context); + final double endIndent = getEffectiveEndIndent(context); + final Color? color = decoration == null ? getEffectiveColor(context) : null; + + switch (direction) { + case Axis.vertical: + return _ConnectorIndent( + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + child: Container( + width: thickness, + color: color, + decoration: decoration, + ), + ); + case Axis.horizontal: + return _ConnectorIndent( + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + child: Container( + height: thickness, + color: color, + decoration: decoration, + ), + ); + } + } +} + +/// A thin dashed line, with padding on either side. +/// +/// The box's total cross axis size(width or height, depend on [direction]) is +/// controlled by [space]. +/// +/// The appropriate padding is automatically computed from the cross axis size. +/// +/// See also: +/// +/// * [DashedLinePainter], which is painter that draws this connector. +class DashedLineConnector extends Connector { + /// Creates a dashed line connector. + /// + /// The [thickness], [space], [indent], and [endIndent] must be null or + /// non-negative. + const DashedLineConnector({ + Key? key, + Axis? direction, + double? thickness, + this.dash, + this.gap, + double? space, + double? indent, + double? endIndent, + Color? color, + this.gapColor, + }) : super( + key: key, + direction: direction, + thickness: thickness, + space: space, + indent: indent, + endIndent: endIndent, + color: color, + ); + + /// The dash size of the line drawn within the connector. + /// + /// If this is null, then this defaults to 1.0. + final double? dash; + + /// The gap of the line drawn within the connector. + /// + /// If this is null, then this defaults to 1.0. + final double? gap; + + /// The color to use when painting the gap in the line. + /// + /// If this is null, then the [Colors.transparent] is used. + final Color? gapColor; + + @override + Widget build(BuildContext context) { + final Axis direction = getEffectiveDirection(context); + return _ConnectorIndent( + direction: direction, + indent: getEffectiveIndent(context), + endIndent: getEffectiveEndIndent(context), + space: getEffectiveSpace(context), + child: CustomPaint( + painter: DashedLinePainter( + direction: direction, + color: getEffectiveColor(context), + strokeWidth: getEffectiveThickness(context), + dashSize: dash ?? 1.0, + gapSize: gap ?? 1.0, + gapColor: gapColor ?? Colors.transparent, + ), + child: Container(), + ), + ); + } +} + +/// A transparent connector for start, end [TimelineNode] of the [Timeline]. +/// +/// This connector will be not displayed, it only occupies an area. +class TransparentConnector extends Connector { + /// Creates a transparent connector. + /// + /// The [space], [indent], and [endIndent] must be null or non-negative. + const TransparentConnector({ + Key? key, + Axis? direction, + double? indent, + double? endIndent, + double? space, + }) : super( + key: key, + direction: direction, + indent: indent, + endIndent: endIndent, + space: space, + ); + + @override + Widget build(BuildContext context) => _ConnectorIndent( + direction: getEffectiveDirection(context), + indent: getEffectiveIndent(context), + endIndent: getEffectiveEndIndent(context), + space: getEffectiveSpace(context), + child: Container(), + ); +} + +/// Apply indent to [child]. +class _ConnectorIndent extends StatelessWidget { + /// Creates a indent. + /// + /// The [direction]and [child] must be null. And [space], [indent] and + /// [endIndent] must be null or non-negative. + const _ConnectorIndent({ + required this.direction, + required this.space, + required this.child, + Key? key, + this.indent, + this.endIndent, + }) : assert(space == null || space >= 0), + assert(indent == null || indent >= 0), + assert(endIndent == null || endIndent >= 0), + super(key: key); + + /// {@macro timelines.direction} + final Axis direction; + + /// The connector's cross axis size extent. + /// + /// The connector itself is always drawn as a line that is centered within the + /// size specified by this value. + final double? space; + + /// The amount of empty space to the leading edge of the connector. + final double? indent; + + /// The amount of empty space to the trailing edge of the connector. + final double? endIndent; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget child; + + @override + Widget build(BuildContext context) => SizedBox( + width: direction == Axis.vertical ? space : null, + height: direction == Axis.vertical ? null : space, + child: Center( + child: Padding( + padding: direction == Axis.vertical + ? EdgeInsetsDirectional.only( + top: indent ?? 0, + bottom: endIndent ?? 0, + ) + : EdgeInsetsDirectional.only( + start: indent ?? 0, + end: endIndent ?? 0, + ), + child: child, + ), + ), + ); +} diff --git a/packages/deriv_ui/lib/components/timeline/src/indicator_theme.dart b/packages/deriv_ui/lib/components/timeline/src/indicator_theme.dart new file mode 100644 index 000000000..734c1c983 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/indicator_theme.dart @@ -0,0 +1,178 @@ +import 'dart:ui' show lerpDouble; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'indicators.dart'; +import 'timeline_node.dart'; +import 'timeline_theme.dart'; + +/// Defines the visual properties of [DotIndicator], indicators inside +/// [TimelineNode]s. +/// +/// Descendant widgets obtain the current [IndicatorThemeData] object using +/// `IndicatorTheme.of(context)`. Instances of [IndicatorThemeData] can be +/// customized with [IndicatorThemeData.copyWith]. +/// +/// Typically a [IndicatorThemeData] is specified as part of the overall +/// [TimelineTheme] with [TimelineThemeData.indicatorTheme]. +/// +/// All [IndicatorThemeData] properties are `null` by default. When null, the +/// widgets will provide their own defaults. +/// +/// See also: +/// +/// * [TimelineThemeData], which describes the overall theme information for +/// the timeline. +@immutable +class IndicatorThemeData with Diagnosticable { + /// Creates a theme that can be used for [IndicatorTheme] or + /// [TimelineThemeData.indicatorTheme]. + const IndicatorThemeData({ + this.color, + this.size, + this.position, + }); + + /// The color of [DotIndicator]s and indicators inside [TimelineNode]s, and so + /// forth. + final Color? color; + + /// The size of [DotIndicator]s and indicators inside [TimelineNode]s, and so + /// forth in logical pixels. + /// + /// Indicators occupy a square with width and height equal to size. + final double? size; + + /// A position of indicator inside both two connectors. + final double? position; + + /// Creates a copy of this object with the given fields replaced with the new + /// values. + IndicatorThemeData copyWith({ + Color? color, + double? size, + double? position, + }) => + IndicatorThemeData( + color: color ?? this.color, + size: size ?? this.size, + position: position ?? this.position, + ); + + /// Linearly interpolate between two Indicator themes. + /// + /// The argument `t` must not be null. + /// + /// {@macro dart.ui.shadow.lerp} + static IndicatorThemeData lerp( + IndicatorThemeData? a, IndicatorThemeData? b, double t) => + IndicatorThemeData( + color: Color.lerp(a?.color, b?.color, t), + size: lerpDouble(a?.size, b?.size, t), + position: lerpDouble(a?.position, b?.position, t), + ); + + @override + int get hashCode => Object.hash(color, size, position); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IndicatorThemeData && + other.color == color && + other.size == size && + other.position == position; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ColorProperty('color', color, defaultValue: null)) + ..add(DoubleProperty('size', size, defaultValue: null)) + ..add(DoubleProperty('position', size, defaultValue: null)); + } +} + +/// Controls the default color and size of indicators in a widget subtree. +/// +/// The indicator theme is honored by [TimelineNode], [DotIndicator] and +/// [OutlinedDotIndicator] widgets. +class IndicatorTheme extends InheritedTheme { + /// Creates an indicator theme that controls the color and size for + /// [DotIndicator]s, indicators inside [TimelineNode]s. + const IndicatorTheme({ + required this.data, + required Widget child, + Key? key, + }) : super(key: key, child: child); + + /// The properties for descendant [DotIndicator]s, indicators inside + /// [TimelineNode]s. + final IndicatorThemeData data; + + /// The data from the closest instance of this class that encloses the given + /// context. + /// + /// Defaults to the current [TimelineThemeData.indicatorTheme]. + /// + /// Typical usage is as follows: + /// + /// ```dart + /// IndicatorThemeData theme = IndicatorTheme.of(context); + /// ``` + static IndicatorThemeData of(BuildContext context) { + final IndicatorTheme? indicatorTheme = + context.dependOnInheritedWidgetOfExactType(); + return indicatorTheme?.data ?? TimelineTheme.of(context).indicatorTheme; + } + + @override + Widget wrap(BuildContext context, Widget child) { + final IndicatorTheme? ancestorTheme = + context.findAncestorWidgetOfExactType(); + return identical(this, ancestorTheme) + ? child + : IndicatorTheme(data: data, child: child); + } + + @override + bool updateShouldNotify(IndicatorTheme oldWidget) => data != oldWidget.data; + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + data.debugFillProperties(properties); + } +} + +/// Indicator component configured through [IndicatorTheme] +mixin ThemedIndicatorComponent on PositionedIndicator { + /// {@template timelines.indicator.color} + /// Defaults to the current [IndicatorTheme] color, if any. + /// + /// If no [IndicatorTheme] and no [TimelineTheme] is specified, indicators + /// will default to blue. + /// {@endtemplate} + Color? get color; + Color getEffectiveColor(BuildContext context) => + color ?? + IndicatorTheme.of(context).color ?? + TimelineTheme.of(context).color; + + /// {@template timelines.indicator.size} + /// Indicators occupy a square with width and height equal to size. + /// + /// Defaults to the current [IndicatorTheme] size, if any. If there is no + /// [IndicatorTheme], or it does not specify an explicit size, then it + /// defaults to own child size(0.0). + /// {@endtemplate} + double? get size; + double? getEffectiveSize(BuildContext context) => + size ?? IndicatorTheme.of(context).size; +} diff --git a/packages/deriv_ui/lib/components/timeline/src/indicators.dart b/packages/deriv_ui/lib/components/timeline/src/indicators.dart new file mode 100644 index 000000000..f58aa7c7a --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/indicators.dart @@ -0,0 +1,262 @@ +import 'package:flutter/material.dart'; +import 'indicator_theme.dart'; +import 'timeline_theme.dart'; + +/// [TimelineNode]'s indicator. +mixin PositionedIndicator on Widget { + /// {@template timelines.indicator.position} + /// If this is null, then the [IndicatorThemeData.position] is used. If that + /// is also null, then this defaults to [TimelineThemeData.indicatorPosition]. + /// {@endtemplate} + double? get position; + double getEffectivePosition(BuildContext context) => + position ?? + IndicatorTheme.of(context).position ?? + TimelineTheme.of(context).indicatorPosition; +} + +/// Abstract class for predefined indicator widgets. +/// +/// See also: +/// +/// * [DotIndicator], which is a [Indicator] that draws dot. +/// * [OutlinedDotIndicator], which is a [Indicator] that draws outlined dot. +/// * [ContainerIndicator], which is a [Indicator] that draws it's child. +abstract class Indicator extends StatelessWidget + with PositionedIndicator, ThemedIndicatorComponent { + /// Creates an indicator. + const Indicator({ + Key? key, + this.size, + this.color, + this.border, + this.position, + this.child, + }) : assert(size == null || size >= 0), + assert(position == null || 0 <= position && position <= 1), + super(key: key); + + /// Creates a dot indicator. + /// + /// See also: + /// + /// * [DotIndicator], exactly the same. + factory Indicator.dot({ + double? size, + Color? color, + double? position, + Border? border, + Widget? child, + }) => + DotIndicator( + size: size, + color: color, + position: position, + border: border, + child: child, + ); + + /// Creates a outlined dot indicator. + /// + /// See also: + /// + /// * [OutlinedDotIndicator], exactly the same. + factory Indicator.outlined({ + double? size, + Color? color, + Color? backgroundColor, + double? position, + double borderWidth = 2.0, + Widget? child, + }) => + OutlinedDotIndicator( + size: size, + color: color, + position: position, + backgroundColor: backgroundColor, + borderWidth: borderWidth, + child: child, + ); + + /// Creates a transparent indicator. + /// + /// See also: + /// + /// * [ContainerIndicator], this is created without child. + factory Indicator.transparent({ + double? size, + double? position, + }) => + ContainerIndicator( + size: size, + position: position, + ); + + /// Creates a widget indicator. + /// + /// See also: + /// + /// * [OutlinedDotIndicator], exactly the same. + factory Indicator.widget({ + double? size, + double? position, + Widget? child, + }) => + ContainerIndicator( + size: size, + position: position, + child: child, + ); + + /// The size of the dot in logical pixels. + /// + /// {@macro timelines.indicator.size} + @override + final double? size; + + /// The color to use when drawing the dot. + /// + /// {@macro timelines.indicator.color} + @override + final Color? color; + + /// The position of a indicator between the two connectors. + /// + /// {@macro timelines.indicator.position} + @override + final double? position; + + /// The border to use when drawing the dot's outline. + final BoxBorder? border; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget? child; +} + +/// A widget that displays an [child]. The [child] if null, the indicator is not +/// visible. +class ContainerIndicator extends Indicator { + /// Creates a container indicator. + const ContainerIndicator({ + Key? key, + double? size, + double? position, + this.child, + }) : super( + key: key, + size: size, + position: position, + color: Colors.transparent, + ); + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget? child; + + @override + Widget build(BuildContext context) { + final double? size = getEffectiveSize(context); + return Container( + width: size, + height: size, + child: child, + ); + } +} + +/// A widget that displays an dot. +class DotIndicator extends Indicator { + /// Creates a dot indicator. + /// + /// The [size] must be null or non-negative. + const DotIndicator({ + Key? key, + double? size, + Color? color, + double? position, + this.border, + this.child, + }) : super( + key: key, + size: size, + color: color, + position: position, + ); + + /// The border to use when drawing the dot's outline. + final BoxBorder? border; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget? child; + + @override + Widget build(BuildContext context) { + final double? effectiveSize = getEffectiveSize(context); + final Color effectiveColor = getEffectiveColor(context); + return Center( + child: Container( + width: effectiveSize ?? ((child == null) ? 15.0 : null), + height: effectiveSize ?? ((child == null) ? 15.0 : null), + child: child, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: effectiveColor, + border: border, + ), + ), + ); + } +} + +/// A widget that displays an outlined dot. +class OutlinedDotIndicator extends Indicator { + /// Creates a outlined dot indicator. + /// + /// The [size] must be null or non-negative. + const OutlinedDotIndicator({ + Key? key, + double? size, + Color? color, + double? position, + this.backgroundColor, + this.borderWidth = 2.0, + this.child, + }) : assert(size == null || size >= 0), + assert(position == null || 0 <= position && position <= 1), + super( + key: key, + size: size, + color: color, + position: position, + ); + + /// The color to use when drawing the dot in outline. + /// + /// {@macro timelines.indicator.color} + final Color? backgroundColor; + + /// The width of this outline, in logical pixels. + final double borderWidth; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget? child; + + @override + Widget build(BuildContext context) => DotIndicator( + size: size, + color: backgroundColor ?? Colors.transparent, + position: position, + border: Border.all( + color: color ?? getEffectiveColor(context), + width: borderWidth, + ), + child: child, + ); +} diff --git a/packages/deriv_ui/lib/components/timeline/src/line_painter.dart b/packages/deriv_ui/lib/components/timeline/src/line_painter.dart new file mode 100644 index 000000000..7b7a2168e --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/line_painter.dart @@ -0,0 +1,206 @@ +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'connectors.dart'; + +/// Paints a [DashedLineConnector]. +/// +/// Draw the line like this: +/// ``` +/// 0 > [dash][gap][dash][gap] < constraints size +/// ``` +/// +/// [dashSize] specifies the size of [dash]. and [gapSize] specifies the size of +/// [gap]. +/// +/// When using the default colors, this painter draws a dotted line or dashed +/// line that familiar. +/// If set other [gapColor], this painter draws a line that alternates between +/// two colors. +class DashedLinePainter extends CustomPainter { + /// Creates a dashed line painter. + /// + /// The [dashSize] argument must be 1 or more, and the [gapSize] and + /// [strokeWidth] arguments must be positive numbers. + /// + /// The [direction], [color], [gapColor] and [strokeCap] arguments must not be + /// null. + const DashedLinePainter({ + required this.direction, + required this.color, + this.gapColor = Colors.transparent, + this.dashSize = 1.0, + this.gapSize = 1.0, + this.strokeWidth = 1.0, + this.strokeCap = StrokeCap.square, + }) : assert(dashSize >= 1), + assert(gapSize >= 0), + assert(strokeWidth >= 0); + + /// {@macro timelines.direction} + final Axis direction; + + /// The color to paint dash of line. + final Color color; + + /// The color to paint gap(another dash) of line. + final Color gapColor; + + /// The size of dash + final double dashSize; + + /// The size of gap, it also draws [gapColor] + final double gapSize; + + /// The stroke width of dash and gap. + final double strokeWidth; + + /// Styles to use for line endings. + final StrokeCap strokeCap; + + @override + void paint(Canvas canvas, Size size) { + final Paint paint = Paint() + ..strokeWidth = strokeWidth + ..strokeCap = strokeCap + ..style = PaintingStyle.stroke; + + _DashOffset offset = _DashOffset( + containerSize: size, + strokeWidth: strokeWidth, + dashSize: dashSize, + gapSize: gapSize, + axis: direction, + ); + + while (offset.hasNext) { + // draw dash + paint.color = color; + canvas.drawLine( + offset, + offset.translateDashSize(), + paint, + ); + offset = offset.translateDashSize(); + + // draw gap + if (gapColor != Colors.transparent) { + paint.color = gapColor; + canvas.drawLine( + offset, + offset.translateGapSize(), + paint, + ); + } + offset = offset.translateGapSize(); + } + } + + @override + bool shouldRepaint(DashedLinePainter oldDelegate) => + direction != oldDelegate.direction || + color != oldDelegate.color || + gapColor != oldDelegate.gapColor || + dashSize != oldDelegate.dashSize || + gapSize != oldDelegate.gapSize || + strokeWidth != oldDelegate.strokeWidth || + strokeCap != oldDelegate.strokeCap; +} + +class _DashOffset extends Offset { + factory _DashOffset({ + required Size containerSize, + required double strokeWidth, + required double dashSize, + required double gapSize, + required Axis axis, + }) => + _DashOffset._( + dx: axis == Axis.vertical ? containerSize.width / 2 : 0, + dy: axis == Axis.vertical ? 0 : containerSize.height / 2, + strokeWidth: strokeWidth, + containerSize: containerSize, + dashSize: dashSize, + gapSize: gapSize, + axis: axis, + ); + + const _DashOffset._({ + required double dx, + required double dy, + required this.strokeWidth, + required this.containerSize, + required this.dashSize, + required this.gapSize, + required this.axis, + }) : super(dx, dy); + + final Size containerSize; + final double strokeWidth; + final double dashSize; + final double gapSize; + final Axis axis; + + double get offset { + if (axis == Axis.vertical) { + return dy; + } else { + return dx; + } + } + + bool get hasNext { + if (axis == Axis.vertical) { + return offset < containerSize.height; + } else { + return offset < containerSize.width; + } + } + + _DashOffset translateDashSize() => _translateDirectionally(dashSize); + + _DashOffset translateGapSize() => + _translateDirectionally(gapSize + strokeWidth); + + _DashOffset _translateDirectionally(double offset) { + if (axis == Axis.vertical) { + return translate(0, offset) as _DashOffset; + } else { + return translate(offset, 0) as _DashOffset; + } + } + + @override + Offset translate(double translateX, double translateY) { + double dx, dy; + if (axis == Axis.vertical) { + dx = this.dx; + dy = this.dy + translateY; + } else { + dx = this.dx + translateX; + dy = this.dy; + } + return copyWith( + dx: min(dx, containerSize.width), + dy: min(dy, containerSize.height), + ); + } + + _DashOffset copyWith({ + double? dx, + double? dy, + Size? containerSize, + double? strokeWidth, + double? dashSize, + double? gapSize, + Axis? axis, + }) => + _DashOffset._( + dx: dx ?? this.dx, + dy: dy ?? this.dy, + containerSize: containerSize ?? this.containerSize, + strokeWidth: strokeWidth ?? this.strokeWidth, + dashSize: dashSize ?? this.dashSize, + gapSize: gapSize ?? this.gapSize, + axis: axis ?? this.axis, + ); +} diff --git a/packages/deriv_ui/lib/components/timeline/src/timeline_node.dart b/packages/deriv_ui/lib/components/timeline/src/timeline_node.dart new file mode 100644 index 000000000..c1715f73d --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/timeline_node.dart @@ -0,0 +1,216 @@ +import 'package:flutter/material.dart'; +import 'connectors.dart'; +import 'indicators.dart'; +import 'timeline_theme.dart'; +import 'util.dart'; + +/// [TimelineTile]'s timeline node +mixin TimelineTileNode on Widget { + /// {@template timelines.node.position} + /// If this is null, then the [TimelineThemeData.nodePosition] is used. + /// {@endtemplate} + double? get position; + double getEffectivePosition(BuildContext context) => + position ?? TimelineTheme.of(context).nodePosition; +} + +/// A widget that displays indicator and two connectors. +/// +/// The [indicator] displayed between the [startConnector] and [endConnector] +class TimelineNode extends StatelessWidget with TimelineTileNode { + /// Creates a timeline node. + /// + /// The [indicatorPosition] must be null or a value between 0 and 1. + const TimelineNode({ + Key? key, + this.direction, + this.startConnector, + this.endConnector, + this.indicator = const ContainerIndicator(), + this.indicatorPosition, + this.position, + this.overlap, + }) : assert(indicatorPosition == null || + 0 <= indicatorPosition && indicatorPosition <= 1), + super(key: key); + + /// Creates a timeline node that connects the dot indicator in a solid line. + TimelineNode.simple({ + Key? key, + Axis? direction, + Color? color, + double? lineThickness, + double? nodePosition, + double? indicatorPosition, + double? indicatorSize, + Widget? indicatorChild, + double? indent, + double? endIndent, + bool drawStartConnector = true, + bool drawEndConnector = true, + bool? overlap, + }) : this( + key: key, + direction: direction, + startConnector: drawStartConnector + ? SolidLineConnector( + direction: direction, + color: color, + thickness: lineThickness, + indent: indent, + endIndent: endIndent, + ) + : null, + endConnector: drawEndConnector + ? SolidLineConnector( + direction: direction, + color: color, + thickness: lineThickness, + indent: indent, + endIndent: endIndent, + ) + : null, + indicator: DotIndicator( + child: indicatorChild, + position: indicatorPosition, + size: indicatorSize, + color: color, + ), + indicatorPosition: indicatorPosition, + position: nodePosition, + overlap: overlap, + ); + + /// {@macro timelines.direction} + final Axis? direction; + + /// The connector of the start edge of this node + final Widget? startConnector; + + /// The connector of the end edge of this node + final Widget? endConnector; + + /// The indicator of the node + final Widget indicator; + + /// The position of a indicator between the two connectors. + /// + /// {@macro timelines.indicator.position} + final double? indicatorPosition; + + /// A position of timeline node between both two contents. + /// + /// {@macro timelines.node.position} + @override + final double? position; + + /// Determine whether each connectors and indicator will overlap. + /// + /// When each connectors overlap, they are drawn from the center offset of the + /// indicator. + final bool? overlap; + + double _getEffectiveIndicatorPosition(BuildContext context) { + double? indicatorPosition = this.indicatorPosition; + return indicatorPosition ??= (indicator is PositionedIndicator) + ? (indicator as PositionedIndicator).getEffectivePosition(context) + : TimelineTheme.of(context).indicatorPosition; + } + + bool _getEffectiveOverlap(BuildContext context) { + final bool overlap = + this.overlap ?? TimelineTheme.of(context).nodeItemOverlap; + return overlap; + } + + @override + Widget build(BuildContext context) { + final Axis direction = + this.direction ?? TimelineTheme.of(context).direction; + final bool overlap = _getEffectiveOverlap(context); + //TODO: support both flex and logical pixel + final double indicatorFlex = _getEffectiveIndicatorPosition(context); + Widget line = indicator; + final List lineItems = [ + if (indicatorFlex > 0) + Flexible( + flex: (indicatorFlex * kFlexMultiplier).toInt(), + child: startConnector ?? const TransparentConnector(), + ), + if (!overlap) indicator, + if (indicatorFlex < 1) + Flexible( + flex: ((1 - indicatorFlex) * kFlexMultiplier).toInt(), + child: endConnector ?? const TransparentConnector(), + ), + ]; + + switch (direction) { + case Axis.vertical: + line = Column( + mainAxisSize: MainAxisSize.min, + children: lineItems, + ); + break; + case Axis.horizontal: + line = Row( + mainAxisSize: MainAxisSize.min, + children: lineItems, + ); + break; + } + + Widget result; + if (overlap) { + Widget positionedIndicator = indicator; + final List positionedIndicatorItems = [ + if (indicatorFlex > 0) + Flexible( + flex: (indicatorFlex * kFlexMultiplier).toInt(), + child: const TransparentConnector(), + ), + indicator, + Flexible( + flex: ((1 - indicatorFlex) * kFlexMultiplier).toInt(), + child: const TransparentConnector(), + ), + ]; + + switch (direction) { + case Axis.vertical: + positionedIndicator = Column( + mainAxisSize: MainAxisSize.min, + children: positionedIndicatorItems, + ); + break; + case Axis.horizontal: + positionedIndicator = Row( + mainAxisSize: MainAxisSize.min, + children: positionedIndicatorItems, + ); + break; + } + + result = Stack( + alignment: Alignment.center, + children: [ + line, + positionedIndicator, + ], + ); + } else { + result = line; + } + + if (TimelineTheme.of(context).direction != direction) { + result = TimelineTheme( + data: TimelineTheme.of(context).copyWith( + direction: direction, + ), + child: result, + ); + } + + return result; + } +} diff --git a/packages/deriv_ui/lib/components/timeline/src/timeline_theme.dart b/packages/deriv_ui/lib/components/timeline/src/timeline_theme.dart new file mode 100644 index 000000000..a1c116fd6 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/timeline_theme.dart @@ -0,0 +1,373 @@ +import 'dart:ui'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'connector_theme.dart'; +import 'indicator_theme.dart'; +import 'timelines.dart'; + +/// Applies a theme to descendant timeline widgets. +/// +/// A theme describes the colors and typographic choices of an application. +/// +/// Descendant widgets obtain the current theme's [TimelineThemeData] object +/// using [TimelineTheme.of]. When a widget uses [TimelineTheme.of], it is +/// automatically rebuilt if the theme later changes, so that the changes can be +/// applied. +/// +/// See also: +/// +/// * [TimelineThemeData], which describes the actual configuration of a theme. +class TimelineTheme extends StatelessWidget { + /// Applies the given theme [data] to [child]. + /// + /// The [data] and [child] arguments must not be null. + const TimelineTheme({ + required this.data, + required this.child, + Key? key, + }) : super(key: key); + + /// Specifies the direction for descendant widgets. + final TimelineThemeData data; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget child; + + static final TimelineThemeData _kFallbackTheme = TimelineThemeData.fallback(); + + /// The data from the closest [TimelineTheme] instance that encloses the given + /// context. + /// + /// Defaults to [ThemeData.fallback] if there is no [Theme] in the given + /// build context. + /// + /// When the [TimelineTheme] is actually created in the same `build` function + /// (possibly indirectly, e.g. as part of a [Timeline]), the `context` + /// argument to the `build` function can't be used to find the [TimelineTheme] + /// (since it's "above" the widget being returned). In such cases, the + /// following technique with a [Builder] can be used to provide a new scope + /// with a [BuildContext] that is "under" the [TimelineTheme]: + /// + /// ```dart + /// @override + /// Widget build(BuildContext context) { + /// // TODO: replace to Timeline + /// return TimelineTheme( + /// data: TimelineThemeData.vertical(), + /// child: Builder( + /// // Create an inner BuildContext so that we can refer to the Theme with TimelineTheme.of(). + /// builder: (BuildContext context) { + /// return Center( + /// child: TimelineNode( + /// direction: TimelineTheme.of(context).direction, + /// child: Text('Example'), + /// ), + /// ); + /// }, + /// ), + /// ); + /// } + /// ``` + static TimelineThemeData of(BuildContext context) { + final _InheritedTheme? inheritedTheme = + context.dependOnInheritedWidgetOfExactType<_InheritedTheme>(); + return inheritedTheme?.theme.data ?? _kFallbackTheme; + } + + @override + Widget build(BuildContext context) => _InheritedTheme( + theme: this, + child: IndicatorTheme( + data: data.indicatorTheme, + child: child, + ), + ); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('data', data, showName: false)); + } +} + +class _InheritedTheme extends InheritedTheme { + const _InheritedTheme({ + required this.theme, + required Widget child, + Key? key, + }) : super(key: key, child: child); + + final TimelineTheme theme; + + @override + Widget wrap(BuildContext context, Widget child) { + final _InheritedTheme? ancestorTheme = + context.findAncestorWidgetOfExactType<_InheritedTheme>(); + return identical(this, ancestorTheme) + ? child + : TimelineTheme(data: theme.data, child: child); + } + + @override + bool updateShouldNotify(_InheritedTheme old) => theme.data != old.theme.data; +} + +/// Defines the configuration of the overall visual [TimelineTheme] for a +/// [Timeline] or a widget subtree within the app. +/// +/// The [Timeline] theme property can be used to configure the appearance of the +/// entire timeline. Widget subtree's within an timeline can override the +/// timeline's theme by including a [TimelineTheme] widget at the top of the +/// subtree. +/// +/// Widgets whose appearance should align with the overall theme can obtain the +/// current theme's configuration with [TimelineTheme.of]. +/// +/// The static [TimelineTheme.of] method finds the [TimelineThemeData] value +/// specified for the nearest [BuildContext] ancestor. This lookup is +/// inexpensive, essentially just a single HashMap access. It can sometimes be a +/// little confusing because [TimelineTheme.of] can not see a [TimelineTheme] +/// widget that is defined in the current build method's context. To overcome +/// that, create a new custom widget for the subtree that appears below the new +/// [TimelineTheme], or insert a widget that creates a new BuildContext, like +/// [Builder]. +/// +/// {@tool snippet} +/// In this example, the [Container] widget uses [Theme.of] to retrieve the +/// color from the theme's [color] to draw an amber square. +/// The [Builder] widget separates the parent theme's [BuildContext] from the +/// child's [BuildContext]. +/// +/// ![](https://flutter.github.io/assets-for-api-docs/assets/material/theme_data.png) +/// +/// ```dart +/// TimelineTheme( +/// data: TimelineThemeData( +/// color: Colors.red, +/// ), +/// child: Builder( +/// builder: (BuildContext context) { +/// return Container( +/// width: 100, +/// height: 100, +/// color: TimelineTheme.of(context).color, +/// ); +/// }, +/// ), +/// ) +/// ``` +/// {@end-tool} +/// +/// {@tool snippet} +@immutable +class TimelineThemeData with Diagnosticable { + /// Create a [TimelineThemeData] that's used to configure a [TimelineTheme]. + /// + /// See also: + /// + /// * [TimelineThemeData.vertical], which creates a vertical direction + /// TimelineThemeData. + /// * [TimelineThemeData.horizontal], which creates a horizontal direction + /// TimelineThemeData. + factory TimelineThemeData({ + Axis? direction, + Color? color, + double? nodePosition, + bool? nodeItemOverlap, + double? indicatorPosition, + IndicatorThemeData? indicatorTheme, + ConnectorThemeData? connectorTheme, + }) { + direction ??= Axis.vertical; + color ??= Colors + .blue; // TODO: Need to change the default color to the theme color? + nodePosition ??= 0.5; + nodeItemOverlap ??= false; + indicatorPosition ??= 0.5; + indicatorTheme ??= const IndicatorThemeData(); + connectorTheme ??= const ConnectorThemeData(); + return TimelineThemeData.raw( + direction: direction, + color: color, + nodePosition: nodePosition, + nodeItemOverlap: nodeItemOverlap, + indicatorPosition: indicatorPosition, + indicatorTheme: indicatorTheme, + connectorTheme: connectorTheme, + ); + } + + /// The default direction theme. Same as [TimelineThemeData.vertical]. + /// + /// This is used by [TimelineTheme.of] when no theme has been specified. + factory TimelineThemeData.fallback() => TimelineThemeData.vertical(); + + /// Create a [TimelineThemeData] given a set of exact values. All the values + /// must be specified. They all must also be non-null. + /// + /// This will rarely be used directly. It is used by [lerp] to create + /// intermediate themes based on two themes created with the + /// [TimelineThemeData] constructor. + const TimelineThemeData.raw({ + required this.direction, + required this.color, + required this.nodePosition, + required this.nodeItemOverlap, + required this.indicatorPosition, + required this.indicatorTheme, + required this.connectorTheme, + }); + + /// A default vertical theme. + factory TimelineThemeData.vertical() => TimelineThemeData( + direction: Axis.vertical, + ); + + /// A default horizontal theme. + factory TimelineThemeData.horizontal() => TimelineThemeData( + direction: Axis.horizontal, + ); + + /// {@macro timelines.direction} + final Axis direction; + + /// The color for major parts of the timeline (indicator, connector, etc) + final Color color; + + /// The position for [TimelineNode] in [TimelineTile]. + /// + /// Defaults to 0.5. + final double nodePosition; + + /// Determine whether each connectors and indicator will overlap in + /// [TimelineNode]. + /// + /// When each connectors overlap, they are drawn from the center offset of the + /// indicator. + final bool nodeItemOverlap; + + /// The position for indicator in [TimelineNode]. + /// + /// Defaults to 0.5. + final double indicatorPosition; + + /// A theme for customizing the appearance and layout of + /// [ThemedIndicatorComponent] widgets. + final IndicatorThemeData indicatorTheme; + + /// A theme for customizing the appearance and layout of + /// [ThemedConnectorComponent] widgets. + final ConnectorThemeData connectorTheme; + + /// Creates a copy of this theme but with the given fields replaced with the + /// new values. + TimelineThemeData copyWith({ + Axis? direction, + Color? color, + double? nodePosition, + bool? nodeItemOverlap, + double? indicatorPosition, + IndicatorThemeData? indicatorTheme, + ConnectorThemeData? connectorTheme, + }) => + TimelineThemeData.raw( + direction: direction ?? this.direction, + color: color ?? this.color, + nodePosition: nodePosition ?? this.nodePosition, + nodeItemOverlap: nodeItemOverlap ?? this.nodeItemOverlap, + indicatorPosition: indicatorPosition ?? this.indicatorPosition, + indicatorTheme: indicatorTheme ?? this.indicatorTheme, + connectorTheme: connectorTheme ?? this.connectorTheme, + ); + + /// Linearly interpolate between two themes. + /// + /// The arguments must not be null. + /// + /// {@macro dart.ui.shadow.lerp} + static TimelineThemeData lerp( + TimelineThemeData a, TimelineThemeData b, double t) => + // Warning: make sure these properties are in the exact same order as in + // hashValues() and in the raw constructor and in the order of fields in + // the class and in the lerp() method. + TimelineThemeData.raw( + direction: t < 0.5 ? a.direction : b.direction, + color: Color.lerp(a.color, b.color, t)!, + nodePosition: lerpDouble(a.nodePosition, b.nodePosition, t)!, + nodeItemOverlap: t < 0.5 ? a.nodeItemOverlap : b.nodeItemOverlap, + indicatorPosition: + lerpDouble(a.indicatorPosition, b.indicatorPosition, t)!, + indicatorTheme: + IndicatorThemeData.lerp(a.indicatorTheme, b.indicatorTheme, t), + connectorTheme: + ConnectorThemeData.lerp(a.connectorTheme, b.connectorTheme, t), + ); + + @override + bool operator ==(Object other) { + if (other.runtimeType != runtimeType) { + return false; + } + // Warning: make sure these properties are in the exact same order as in + // hashValues() and in the raw constructor and in the order of fields in + // the class and in the lerp() method. + return other is TimelineThemeData && + other.direction == direction && + other.color == color && + other.nodePosition == nodePosition && + other.nodeItemOverlap == nodeItemOverlap && + other.indicatorPosition == indicatorPosition && + other.indicatorTheme == indicatorTheme && + other.connectorTheme == connectorTheme; + } + + @override + int get hashCode { + // Warning: For the sanity of the reader, please make sure these properties + // are in the exact same order as in operator == and in the raw constructor + // and in the order of fields in the class and in the lerp() method. + final List values = [ + direction, + color, + nodePosition, + nodeItemOverlap, + indicatorPosition, + indicatorTheme, + connectorTheme, + ]; + return Object.hashAll(values); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + final TimelineThemeData defaultData = TimelineThemeData.fallback(); + properties + ..add(DiagnosticsProperty('direction', direction, + defaultValue: defaultData.direction, level: DiagnosticLevel.debug)) + ..add(ColorProperty('color', color, + defaultValue: defaultData.color, level: DiagnosticLevel.debug)) + ..add(DoubleProperty('nodePosition', nodePosition, + defaultValue: defaultData.nodePosition, level: DiagnosticLevel.debug)) + ..add(FlagProperty('nodeItemOverlap', + value: nodeItemOverlap, ifTrue: 'overlap connector and indicator')) + ..add(DoubleProperty('indicatorPosition', indicatorPosition, + defaultValue: defaultData.indicatorPosition, + level: DiagnosticLevel.debug)) + ..add(DiagnosticsProperty( + 'indicatorTheme', + indicatorTheme, + defaultValue: defaultData.indicatorTheme, + level: DiagnosticLevel.debug, + )) + ..add(DiagnosticsProperty( + 'connectorTheme', + connectorTheme, + defaultValue: defaultData.connectorTheme, + level: DiagnosticLevel.debug, + )); + } +} diff --git a/packages/deriv_ui/lib/components/timeline/src/timeline_tile.dart b/packages/deriv_ui/lib/components/timeline/src/timeline_tile.dart new file mode 100644 index 000000000..9884f80b3 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/timeline_tile.dart @@ -0,0 +1,215 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'indicator_theme.dart'; +import 'timeline_node.dart'; +import 'timeline_theme.dart'; +import 'util.dart'; + +/// Align the timeline node within the timeline tile. +enum TimelineNodeAlign { + /// Align [TimelineTile.node] to start side. + start, + + /// Align [TimelineTile.node] to end side. + end, + + /// Align according to the [TimelineTile.nodePosition]. + basic, +} + +/// A widget that displays timeline node and two contents. +/// +/// The [contents] are displayed on the end side, and the [oppositeContents] are +/// displayed on the start side. +/// The [node] is displayed between the two. +class TimelineTile extends StatelessWidget { + const TimelineTile({ + required this.node, + Key? key, + this.direction, + this.nodeAlign = TimelineNodeAlign.basic, + this.nodePosition, + this.contents, + this.oppositeContents, + this.mainAxisExtent, + this.crossAxisExtent, + }) : assert( + nodeAlign == TimelineNodeAlign.basic || + (nodeAlign != TimelineNodeAlign.basic && nodePosition == null), + 'Cannot provide both a nodeAlign and a nodePosition', + ), + assert(nodePosition == null || nodePosition >= 0), + super(key: key); + + /// {@template timelines.direction} + /// The axis along which the timeline scrolls. + /// {@endtemplate} + final Axis? direction; + + /// A widget that displays indicator and two connectors. + final Widget node; + + /// Align the [node] within the timeline tile. + /// + /// If try to use indicators with different sizes in each timeline tile, the + /// timeline node may be broken. + /// This can be prevented by set [IndicatorThemeData.size] to an appropriate + /// size. + /// + /// If [nodeAlign] is not [TimelineNodeAlign.basic], then [nodePosition] is + /// ignored. + final TimelineNodeAlign nodeAlign; + + /// A position of [node] inside both two contents. + /// + /// {@macro timelines.node.position} + final double? nodePosition; + + /// The contents to display inside the timeline tile. + final Widget? contents; + + /// The contents to display on the opposite side of the [contents]. + final Widget? oppositeContents; + + /// The extent of the child in the scrolling axis. + /// If the scroll axis is vertical, this extent is the child's height. If the + /// scroll axis is horizontal, this extent is the child's width. + /// + /// If non-null, forces the tile to have the given extent in the scroll + /// direction. + /// + /// Specifying an [mainAxisExtent] is more efficient than letting the tile + /// determine their own extent because the because it don't use the Intrinsic + /// widget([IntrinsicHeight]/[IntrinsicWidth]) when building. + final double? mainAxisExtent; + + /// The extent of the child in the non-scrolling axis. + /// + /// If the scroll axis is vertical, this extent is the child's width. If the + /// scroll axis is horizontal, this extent is the child's height. + final double? crossAxisExtent; + + double _getEffectiveNodePosition(BuildContext context) { + if (nodeAlign == TimelineNodeAlign.start) { + return 0; + } + if (nodeAlign == TimelineNodeAlign.end) { + return 1; + } + double? nodePosition = this.nodePosition; + return nodePosition ??= (node is TimelineTileNode) + ? (node as TimelineTileNode).getEffectivePosition(context) + : TimelineTheme.of(context).nodePosition; + } + + @override + Widget build(BuildContext context) { + // TODO: reduce direction check + final Axis direction = + this.direction ?? TimelineTheme.of(context).direction; + final double nodeFlex = + _getEffectiveNodePosition(context) * kFlexMultiplier; + + final double minNodeExtent = + TimelineTheme.of(context).indicatorTheme.size ?? 0.0; + final List items = [ + if (nodeFlex > 0) + Expanded( + flex: nodeFlex.toInt(), + child: Align( + alignment: direction == Axis.vertical + ? AlignmentDirectional.centerEnd + : Alignment.bottomCenter, + child: oppositeContents ?? const SizedBox.shrink(), + ), + ), + ConstrainedBox( + constraints: BoxConstraints( + minWidth: direction == Axis.vertical ? minNodeExtent : 0.0, + minHeight: direction == Axis.vertical ? 0.0 : minNodeExtent, + ), + child: node, + ), + if (nodeFlex < kFlexMultiplier) + Expanded( + flex: (kFlexMultiplier - nodeFlex).toInt(), + child: Align( + alignment: direction == Axis.vertical + ? AlignmentDirectional.centerStart + : Alignment.topCenter, + child: contents ?? const SizedBox.shrink(), + ), + ), + ]; + + Widget result; + switch (direction) { + case Axis.vertical: + result = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: items, + ); + + if (mainAxisExtent != null) { + result = SizedBox( + width: crossAxisExtent, + height: mainAxisExtent, + child: result, + ); + } else { + result = IntrinsicHeight( + child: result, + ); + + if (crossAxisExtent != null) { + result = SizedBox( + width: crossAxisExtent, + child: result, + ); + } + } + break; + case Axis.horizontal: + result = Column( + mainAxisAlignment: MainAxisAlignment.center, + children: items, + ); + if (mainAxisExtent != null) { + result = SizedBox( + width: mainAxisExtent, + height: crossAxisExtent, + child: result, + ); + } else { + result = IntrinsicWidth( + child: result, + ); + + if (crossAxisExtent != null) { + result = SizedBox( + height: crossAxisExtent, + child: result, + ); + } + } + break; + default: + throw ArgumentError.value(direction, '$direction is invalid.'); + } + + result = Align( + child: result, + ); + + if (TimelineTheme.of(context).direction != direction) { + result = TimelineTheme( + data: TimelineTheme.of(context).copyWith( + direction: direction, + ), + child: result, + ); + } + + return result; + } +} diff --git a/packages/deriv_ui/lib/components/timeline/src/timeline_tile_builder.dart b/packages/deriv_ui/lib/components/timeline/src/timeline_tile_builder.dart new file mode 100644 index 000000000..d357e7e13 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/timeline_tile_builder.dart @@ -0,0 +1,545 @@ +import 'package:flutter/material.dart'; +import 'connectors.dart'; +import 'indicators.dart'; +import 'timeline_node.dart'; +import 'timeline_theme.dart'; +import 'timeline_tile.dart'; + +/// How a contents displayed be into timeline. +/// +/// See also: +/// * [TimelineTileBuilder.fromStyle] +enum ContentsAlign { + /// The contents aligned end of timeline. And the opposite contents aligned + /// start of timeline. + /// + /// Example: + /// ``` + /// opposite contents | contents + /// opposite contents | contents + /// opposite contents | contents + /// ``` + basic, + + /// The contents aligned start of timeline. And the opposite contents aligned + /// end of timeline. + /// + /// Example: + /// + /// ``` + /// contents | opposite contents + /// contents | opposite contents + /// contents | opposite contents + /// ``` + reverse, + + /// The contents and opposite contents displayed alternating. + /// + /// Example: + /// ``` + /// contents | opposite contents + /// opposite contents | contents + /// contents | opposite contents + /// opposite contents | contents + /// contents | opposite contents + /// ``` + alternating, +} + +/// An enum that representing the direction the connector is connected through +/// the builder. +/// +/// See also: +/// +/// * [TimelineTileBuilder.connected], which is how the builder uses this enum +/// to connect each connector. +/// * [TimelineTileBuilder.connectedFromStyle], which is how the builder uses +/// this enum to connect each connector. +enum ConnectionDirection { before, after } + +/// An enum that representing the connector type in [TimelineNode]. +/// +/// For example, if the timeline direction is Axis.horizontal and the text +/// direction is LTR: +/// ``` +/// start end +/// ---- O ---- +/// ``` +/// See also: +/// +/// * [ConnectedConnectorBuilder], which is use this. +enum ConnectorType { start, end } + +/// An enum that determines the style of indicator in timeline tile builder. +/// +/// TODO: replace with class to support parameters +/// +/// See also: +/// +/// * [TimelineTileBuilder.fromStyle], which is use this. +/// * [TimelineTileBuilder.connectedFromStyle], which is use this. +enum IndicatorStyle { + /// Draw dot indicator. + dot, + + /// Draw outlined dot indicator. + outlined, + + /// Draw container indicator. TODO: need child to builds... + container, + + /// Draw transparent indicator. (invisible indicator) + transparent, +} + +/// Types of connectors displayed into timeline +/// +/// See also: +/// * [TimelineTileBuilder.fromStyle]. +enum ConnectorStyle { + /// Draw solid line connector. + solidLine, + + /// Draw dashed line connector. + dashedLine, + + /// Draw transparent connector. (invisible connector) + transparent, +} + +/// Signature for a function that creates a connected connector widget for a +/// given index and type, e.g., in a timeline tile builder. +typedef ConnectedConnectorBuilder = Widget? Function( + BuildContext context, int index, ConnectorType type); + +/// Signature for a function that creates a typed value for a given index, e.g., +/// in a timeline tile builder. +/// +/// Used by [TimelineTileBuilder] that use lazily-generated typed value. +typedef IndexedValueBuilder = T Function(BuildContext context, int index); + +/// WARNING: The interface of this class is not yet clear. It may change +/// frequently. +/// +/// A delegate that supplies [TimelineTile] for timeline using a builder +/// callback. +class TimelineTileBuilder { + /// Create a connected tile builder, which builds tiles using each component + /// builder. + /// + /// Check below for how to build: + /// + /// Original build system: + /// + /// ``` + /// | <-- builder(0) + /// O contents1 <-- builder(0) + /// | <-- builder(0) + /// | <-- builder(1) + /// O contents2 <-- builder(1) + /// | <-- builder(1) + /// ``` + /// + /// Connected build system(before): + /// + /// ``` + /// | <-- draw if provided [firstConnectorBuilder] + /// O contents1 <-- builder(0) + /// | <-- builder(1) + /// | <-- builder(1) + /// O contents2 <-- builder(1) + /// | <-- builder(2) + /// | <-- builder(2) + /// O <-- builder(2) + /// | <-- builder(3) + /// .. + /// | <-- draw if provided [lastConnectorBuilder] + /// ``` + /// + /// + /// Connected build system(after): + /// + /// ``` + /// | <-- draw if provided [firstConnectorBuilder] + /// O contents1 <-- builder(0) + /// | <-- builder(0) + /// | <-- builder(0) + /// O contents2 <-- builder(1) + /// | <-- builder(1) + /// | <-- builder(1) + /// O <-- builder(2) + /// | <-- builder(2) + /// .. + /// | <-- draw if provided [lastConnectorBuilder] + /// ``` + /// + /// The above example can be made similar by just set the + /// [TimelineNode.indicatorPosition] as 0 or 1, but the contents position may + /// be limited. + /// + /// {@macro timelines.itemExtentBuilder} + /// + /// See also: + /// + /// * [TimelineTileBuilder.connectedFromStyle], which builds connected tiles + /// from style. + factory TimelineTileBuilder.connected({ + required int itemCount, + ContentsAlign contentsAlign = ContentsAlign.basic, + ConnectionDirection connectionDirection = ConnectionDirection.after, + NullableIndexedWidgetBuilder? contentsBuilder, + NullableIndexedWidgetBuilder? oppositeContentsBuilder, + NullableIndexedWidgetBuilder? indicatorBuilder, + ConnectedConnectorBuilder? connectorBuilder, + WidgetBuilder? firstConnectorBuilder, + WidgetBuilder? lastConnectorBuilder, + double? itemExtent, + IndexedValueBuilder? itemExtentBuilder, + IndexedValueBuilder? nodePositionBuilder, + IndexedValueBuilder? indicatorPositionBuilder, + bool addAutomaticKeepAlives = true, + bool addRepaintBoundaries = true, + bool addSemanticIndexes = true, + }) => + TimelineTileBuilder( + itemCount: itemCount, + contentsAlign: contentsAlign, + contentsBuilder: contentsBuilder, + oppositeContentsBuilder: oppositeContentsBuilder, + indicatorBuilder: indicatorBuilder, + startConnectorBuilder: _createConnectedStartConnectorBuilder( + connectionDirection: connectionDirection, + firstConnectorBuilder: firstConnectorBuilder, + connectorBuilder: connectorBuilder, + ), + endConnectorBuilder: _createConnectedEndConnectorBuilder( + connectionDirection: connectionDirection, + lastConnectorBuilder: lastConnectorBuilder, + connectorBuilder: connectorBuilder, + itemCount: itemCount, + ), + itemExtent: itemExtent, + itemExtentBuilder: itemExtentBuilder, + nodePositionBuilder: nodePositionBuilder, + indicatorPositionBuilder: indicatorPositionBuilder, + ); + + /// Create a connected tile builder, which builds tiles using each style. + /// + /// {@macro timelines.itemExtentBuilder} + /// + /// See also: + /// + /// * [TimelineTileBuilder.connected], which builds connected tiles. + /// * [TimelineTileBuilder.fromStyle], which builds tiles from style. + factory TimelineTileBuilder.connectedFromStyle({ + @required required int itemCount, + ConnectionDirection connectionDirection = ConnectionDirection.after, + NullableIndexedWidgetBuilder? contentsBuilder, + NullableIndexedWidgetBuilder? oppositeContentsBuilder, + ContentsAlign contentsAlign = ContentsAlign.basic, + IndexedValueBuilder? indicatorStyleBuilder, + IndexedValueBuilder? connectorStyleBuilder, + ConnectorStyle firstConnectorStyle = ConnectorStyle.solidLine, + ConnectorStyle lastConnectorStyle = ConnectorStyle.solidLine, + double? itemExtent, + IndexedValueBuilder? itemExtentBuilder, + IndexedValueBuilder? nodePositionBuilder, + IndexedValueBuilder? indicatorPositionBuilder, + }) => + TimelineTileBuilder( + itemCount: itemCount, + contentsAlign: contentsAlign, + contentsBuilder: contentsBuilder, + oppositeContentsBuilder: oppositeContentsBuilder, + indicatorBuilder: (BuildContext context, int index) => + _createStyledIndicatorBuilder( + indicatorStyleBuilder?.call(context, index))(context), + startConnectorBuilder: _createConnectedStartConnectorBuilder( + connectionDirection: connectionDirection, + firstConnectorBuilder: (BuildContext context) => + _createStyledConnectorBuilder(firstConnectorStyle)(context), + connectorBuilder: (BuildContext context, int index, __) => + _createStyledConnectorBuilder( + connectorStyleBuilder?.call(context, index))(context), + ), + endConnectorBuilder: _createConnectedEndConnectorBuilder( + connectionDirection: connectionDirection, + lastConnectorBuilder: (BuildContext context) => + _createStyledConnectorBuilder(lastConnectorStyle)(context), + connectorBuilder: (BuildContext context, int index, __) => + _createStyledConnectorBuilder( + connectorStyleBuilder?.call(context, index))(context), + itemCount: itemCount, + ), + itemExtent: itemExtent, + itemExtentBuilder: itemExtentBuilder, + nodePositionBuilder: nodePositionBuilder, + indicatorPositionBuilder: indicatorPositionBuilder, + ); + + /// Create a tile builder, which builds tiles using each style. + /// + /// {@macro timelines.itemExtentBuilder} + /// TODO: style each index like fromStyleBuilder + /// + /// See also: + /// + /// * [IndicatorStyle] + /// * [ConnectorStyle] + /// * [ContentsAlign] + factory TimelineTileBuilder.fromStyle({ + required int itemCount, + NullableIndexedWidgetBuilder? contentsBuilder, + NullableIndexedWidgetBuilder? oppositeContentsBuilder, + ContentsAlign contentsAlign = ContentsAlign.basic, + IndicatorStyle indicatorStyle = IndicatorStyle.dot, + ConnectorStyle connectorStyle = ConnectorStyle.solidLine, + ConnectorStyle endConnectorStyle = ConnectorStyle.solidLine, + double? itemExtent, + IndexedValueBuilder? itemExtentBuilder, + IndexedValueBuilder? nodePositionBuilder, + IndexedValueBuilder? indicatorPositionBuilder, + bool addAutomaticKeepAlives = true, + bool addRepaintBoundaries = true, + bool addSemanticIndexes = true, + }) => + TimelineTileBuilder( + itemCount: itemCount, + contentsAlign: contentsAlign, + contentsBuilder: contentsBuilder, + oppositeContentsBuilder: oppositeContentsBuilder, + indicatorBuilder: (BuildContext context, int index) => + _createStyledIndicatorBuilder(indicatorStyle)(context), + startConnectorBuilder: (BuildContext context, _) => + _createStyledConnectorBuilder(connectorStyle)(context), + endConnectorBuilder: (BuildContext context, _) => + _createStyledConnectorBuilder(connectorStyle)(context), + itemExtent: itemExtent, + itemExtentBuilder: itemExtentBuilder, + nodePositionBuilder: nodePositionBuilder, + indicatorPositionBuilder: indicatorPositionBuilder, + ); + + /// Create a tile builder, which builds tiles using each component builder. + /// + /// {@template timelines.itemExtentBuilder} + /// If each item has a fixed extent, use [itemExtent], and if each item has a + /// different extent, use [itemExtentBuilder]. + /// {@endtemplate} + /// + /// TODO: need refactoring, is it has many builders...? + factory TimelineTileBuilder({ + required int itemCount, + ContentsAlign contentsAlign = ContentsAlign.basic, + NullableIndexedWidgetBuilder? contentsBuilder, + NullableIndexedWidgetBuilder? oppositeContentsBuilder, + NullableIndexedWidgetBuilder? indicatorBuilder, + NullableIndexedWidgetBuilder? startConnectorBuilder, + NullableIndexedWidgetBuilder? endConnectorBuilder, + double? itemExtent, + IndexedValueBuilder? itemExtentBuilder, + IndexedValueBuilder? nodePositionBuilder, + IndexedValueBuilder? nodeItemOverlapBuilder, + IndexedValueBuilder? indicatorPositionBuilder, + IndexedValueBuilder? themeBuilder, + }) { + assert( + itemExtent == null || itemExtentBuilder == null, + 'Cannot provide both a itemExtent and a itemExtentBuilder.', + ); + + final NullableIndexedWidgetBuilder effectiveContentsBuilder = + _createAlignedContentsBuilder( + align: contentsAlign, + contentsBuilder: contentsBuilder, + oppositeContentsBuilder: oppositeContentsBuilder, + ); + final NullableIndexedWidgetBuilder effectiveOppositeContentsBuilder = + _createAlignedContentsBuilder( + align: contentsAlign, + contentsBuilder: oppositeContentsBuilder, + oppositeContentsBuilder: contentsBuilder, + ); + + return TimelineTileBuilder._( + (BuildContext context, int index) { + final TimelineTile tile = TimelineTile( + mainAxisExtent: itemExtent ?? itemExtentBuilder?.call(context, index), + node: TimelineNode( + indicator: indicatorBuilder?.call(context, index) ?? + Indicator.transparent(), + startConnector: startConnectorBuilder?.call(context, index), + endConnector: endConnectorBuilder?.call(context, index), + overlap: nodeItemOverlapBuilder?.call(context, index), + position: nodePositionBuilder?.call(context, index), + indicatorPosition: indicatorPositionBuilder?.call(context, index), + ), + contents: effectiveContentsBuilder(context, index), + oppositeContents: effectiveOppositeContentsBuilder(context, index), + ); + + final TimelineThemeData? theme = themeBuilder?.call(context, index); + if (theme != null) { + return TimelineTheme( + data: theme, + child: tile, + ); + } else { + return tile; + } + }, + itemCount: itemCount, + ); + } + + const TimelineTileBuilder._( + this._builder, { + required this.itemCount, + }) : assert(itemCount >= 0); + + final IndexedWidgetBuilder _builder; + final int itemCount; + + Widget build(BuildContext context, int index) => _builder(context, index); + + static NullableIndexedWidgetBuilder _createConnectedStartConnectorBuilder({ + ConnectionDirection? connectionDirection, + WidgetBuilder? firstConnectorBuilder, + ConnectedConnectorBuilder? connectorBuilder, + }) => + (BuildContext context, int index) { + if (index == 0) { + if (firstConnectorBuilder != null) { + return firstConnectorBuilder.call(context); + } else { + return null; + } + } + + if (connectionDirection == ConnectionDirection.before) { + return connectorBuilder?.call(context, index, ConnectorType.start); + } else { + return connectorBuilder?.call( + context, index - 1, ConnectorType.start); + } + }; + + static NullableIndexedWidgetBuilder _createConnectedEndConnectorBuilder({ + required int itemCount, + ConnectionDirection? connectionDirection, + WidgetBuilder? lastConnectorBuilder, + ConnectedConnectorBuilder? connectorBuilder, + }) => + (BuildContext context, int index) { + if (index == itemCount - 1) { + if (lastConnectorBuilder != null) { + return lastConnectorBuilder.call(context); + } else { + return null; + } + } + + if (connectionDirection == ConnectionDirection.before) { + return connectorBuilder?.call(context, index + 1, ConnectorType.end); + } else { + return connectorBuilder?.call(context, index, ConnectorType.end); + } + }; + + static NullableIndexedWidgetBuilder _createAlignedContentsBuilder({ + required ContentsAlign align, + NullableIndexedWidgetBuilder? contentsBuilder, + NullableIndexedWidgetBuilder? oppositeContentsBuilder, + }) => + (BuildContext context, int index) { + switch (align) { + case ContentsAlign.alternating: + if (index.isOdd) { + return oppositeContentsBuilder?.call(context, index); + } + + return contentsBuilder?.call(context, index); + case ContentsAlign.reverse: + return oppositeContentsBuilder?.call(context, index); + case ContentsAlign.basic: + default: + return contentsBuilder?.call(context, index); + } + }; + + static WidgetBuilder _createStyledIndicatorBuilder(IndicatorStyle? style) => + (_) { + switch (style) { + case IndicatorStyle.dot: + return Indicator.dot(); + case IndicatorStyle.outlined: + return Indicator.outlined(); + case IndicatorStyle.container: + return Indicator.widget(); + case IndicatorStyle.transparent: + default: + return Indicator.transparent(); + } + }; + + static WidgetBuilder _createStyledConnectorBuilder(ConnectorStyle? style) => + (_) { + switch (style) { + case ConnectorStyle.solidLine: + return Connector.solidLine(); + case ConnectorStyle.dashedLine: + return Connector.dashedLine(); + case ConnectorStyle.transparent: + default: + return Connector.transparent(); + } + }; +} + +int _kDefaultSemanticIndexCallback(Widget _, int localIndex) => localIndex; + +/// The widgets returned from the builder callback are automatically wrapped in +/// [AutomaticKeepAlive] widgets if [addAutomaticKeepAlives] is true +/// (the default) and in [RepaintBoundary] widgets if [addRepaintBoundaries] is +/// true (also the default). +/// +/// ## Accessibility +/// +/// The [CustomScrollView] requires that its semantic children are annotated +/// using [IndexedSemantics]. This is done by default in the delegate with the +/// `addSemanticIndexes` parameter set to true. +/// +/// If multiple delegates are used in a single scroll view, then the indexes +/// will not be correct by default. The `semanticIndexOffset` can be used to +/// offset the semantic indexes of each delegate so that the indexes are +/// monotonically increasing. For example, if a scroll view contains two +/// delegates where the first has 10 children contributing semantics, then the +/// second delegate should offset its children by 10. +/// +/// See also: +/// +/// * [IndexedSemantics], for an example of manually annotating child nodes +/// with semantic indexes. +class TimelineTileBuilderDelegate extends SliverChildBuilderDelegate { + TimelineTileBuilderDelegate( + NullableIndexedWidgetBuilder builder, { + ChildIndexGetter? findChildIndexCallback, + int? childCount, + bool addAutomaticKeepAlives = true, + bool addRepaintBoundaries = true, + bool addSemanticIndexes = true, + SemanticIndexCallback semanticIndexCallback = + _kDefaultSemanticIndexCallback, + int semanticIndexOffset = 0, + }) : super( + builder, + findChildIndexCallback: findChildIndexCallback, + childCount: childCount, + addAutomaticKeepAlives: addAutomaticKeepAlives, + addRepaintBoundaries: addRepaintBoundaries, + addSemanticIndexes: addSemanticIndexes, + semanticIndexCallback: semanticIndexCallback, + semanticIndexOffset: semanticIndexOffset, + ); +} diff --git a/packages/deriv_ui/lib/components/timeline/src/timelines.dart b/packages/deriv_ui/lib/components/timeline/src/timelines.dart new file mode 100644 index 000000000..fa9d61db0 --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/timelines.dart @@ -0,0 +1,483 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +import 'timeline_theme.dart'; +import 'timeline_tile_builder.dart'; + +/// A scrollable timeline of widgets arranged linearly. +class Timeline extends BoxScrollView { + /// Creates a scrollable, linear array of widgets that are created on demand. + /// + /// This constructor is appropriate for list views with a large (or infinite) + /// number of children because the builder is called only for those children + /// that are actually visible. + /// + /// Providing a non-null `itemCount` improves the ability of the [Timeline] to + /// estimate the maximum scroll extent. + /// + /// The `itemBuilder` callback will be called only with indices greater than + /// or equal to zero and less than `itemCount`. + /// + /// The `itemBuilder` should always return a non-null widget, and actually + /// create the widget instances when called. + /// Avoid using a builder that returns a previously-constructed widget; if the + /// timeline view's children are created in advance, or all at once when the + /// [Timeline] itself is created, it is more efficient to use the [Timeline] + /// constructor. Even more efficient, however, is to create the instances on + /// demand using this constructor's `itemBuilder` callback. + /// + /// The `addAutomaticKeepAlives` argument corresponds to the + /// [SliverChildBuilderDelegate.addAutomaticKeepAlives] property. The + /// `addRepaintBoundaries` argument corresponds to the + /// [SliverChildBuilderDelegate.addRepaintBoundaries] property. The + /// `addSemanticIndexes` argument corresponds to the + /// [SliverChildBuilderDelegate.addSemanticIndexes] property. None + /// may be null. + /// + /// [Timeline.builder] by default does not support child reordering. If you + /// are planning to change child order at a + /// later time, consider using [Timeline] or [Timeline.custom]. + factory Timeline.tileBuilder({ + required TimelineTileBuilder builder, Key? key, + Axis? scrollDirection, + bool reverse = false, + ScrollController? controller, + bool? primary, + ScrollPhysics? physics, + bool shrinkWrap = false, + EdgeInsetsGeometry? padding, + // double itemExtent, TODO: fixedExtentTileBuilder? + double? cacheExtent, + int? semanticChildCount, + DragStartBehavior dragStartBehavior = DragStartBehavior.start, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, + String? restorationId, + Clip clipBehavior = Clip.hardEdge, + TimelineThemeData? theme, + }) { + assert(builder.itemCount >= 0); + assert( + semanticChildCount == null || semanticChildCount <= builder.itemCount); + return Timeline.custom( + key: key, + childrenDelegate: SliverChildBuilderDelegate( + builder.build, + childCount: builder.itemCount, + // TODO: apply some fields if needed. + ), + scrollDirection: scrollDirection, + reverse: reverse, + controller: controller, + primary: primary, + physics: physics, + shrinkWrap: shrinkWrap, + padding: padding, + // itemExtent: itemExtent, + cacheExtent: cacheExtent, + semanticChildCount: semanticChildCount ?? builder.itemCount, + dragStartBehavior: dragStartBehavior, + keyboardDismissBehavior: keyboardDismissBehavior, + restorationId: restorationId, + clipBehavior: clipBehavior, + theme: theme, + ); + } + + /// Creates a scrollable, linear array of widgets from an explicit [List]. + /// + /// This constructor is appropriate for timeline views with a small number of + /// children because constructing the [List] requires doing work for every + /// child that could possibly be displayed in the timeline view instead of + /// just those children that are actually visible. + /// + /// It is usually more efficient to create children on demand using + /// [Timeline.builder] because it will create the widget children lazily as + /// necessary. + /// + /// The `addAutomaticKeepAlives` argument corresponds to the + /// [SliverChildListDelegate.addAutomaticKeepAlives] property. The + /// `addRepaintBoundaries` argument corresponds to the + /// [SliverChildListDelegate.addRepaintBoundaries] property. The + /// `addSemanticIndexes` argument corresponds to the + /// [SliverChildListDelegate.addSemanticIndexes] property. None may be null. + Timeline({ + Key? key, + Axis? scrollDirection, + bool reverse = false, + ScrollController? controller, + bool? primary, + ScrollPhysics? physics, + bool shrinkWrap = false, + EdgeInsetsGeometry? padding, + this.itemExtent, + bool addAutomaticKeepAlives = true, + bool addRepaintBoundaries = true, + bool addSemanticIndexes = true, + double? cacheExtent, + List children = const [], + int? semanticChildCount, + DragStartBehavior dragStartBehavior = DragStartBehavior.start, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, + String? restorationId, + Clip clipBehavior = Clip.hardEdge, + this.theme, + }) : childrenDelegate = SliverChildListDelegate( + children, + addAutomaticKeepAlives: addAutomaticKeepAlives, + addRepaintBoundaries: addRepaintBoundaries, + addSemanticIndexes: addSemanticIndexes, + ), + assert(scrollDirection == null || theme == null, + 'Cannot provide both a scrollDirection and a theme.'), + super( + key: key, + scrollDirection: scrollDirection ?? theme?.direction ?? Axis.vertical, + reverse: reverse, + controller: controller, + primary: primary, + physics: physics, + shrinkWrap: shrinkWrap, + padding: padding, + cacheExtent: cacheExtent, + semanticChildCount: semanticChildCount ?? children.length, + dragStartBehavior: dragStartBehavior, + keyboardDismissBehavior: keyboardDismissBehavior, + restorationId: restorationId, + clipBehavior: clipBehavior, + ); + + /// Creates a scrollable, linear array of widgets that are created on demand. + /// + /// This constructor is appropriate for list views with a large (or infinite) + /// number of children because the builder is called only for those children + /// that are actually visible. + /// + /// Providing a non-null `itemCount` improves the ability of the [Timeline] to + /// estimate the maximum scroll extent. + /// + /// The `itemBuilder` callback will be called only with indices greater than + /// or equal to zero and less than `itemCount`. + /// + /// The `itemBuilder` should always return a non-null widget, and actually + /// create the widget instances when called. + /// Avoid using a builder that returns a previously-constructed widget; if the + /// timeline view's children are created in advance, or all at once when the + /// [Timeline] itself is created, it is more efficient to use the [Timeline] + /// constructor. Even more efficient, however, is to create the instances on + /// demand using this constructor's `itemBuilder` callback. + /// + /// The `addAutomaticKeepAlives` argument corresponds to the + /// [SliverChildBuilderDelegate.addAutomaticKeepAlives] property. The + /// `addRepaintBoundaries` argument corresponds to the + /// [SliverChildBuilderDelegate.addRepaintBoundaries] property. The + /// `addSemanticIndexes` argument corresponds to the + /// [SliverChildBuilderDelegate.addSemanticIndexes] property. None + /// may be null. + /// + /// [Timeline.builder] by default does not support child reordering. If you + /// are planning to change child order at a + /// later time, consider using [Timeline] or [Timeline.custom]. + Timeline.builder({ + required IndexedWidgetBuilder itemBuilder, required int itemCount, Key? key, + Axis? scrollDirection, + bool reverse = false, + ScrollController? controller, + bool? primary, + ScrollPhysics? physics, + bool shrinkWrap = false, + EdgeInsetsGeometry? padding, + this.itemExtent, + bool addAutomaticKeepAlives = true, + bool addRepaintBoundaries = true, + bool addSemanticIndexes = true, + double? cacheExtent, + int? semanticChildCount, + DragStartBehavior dragStartBehavior = DragStartBehavior.start, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, + String? restorationId, + Clip clipBehavior = Clip.hardEdge, + this.theme, + }) : assert(itemCount >= 0), + assert(semanticChildCount == null || semanticChildCount <= itemCount), + assert(scrollDirection == null || theme == null, + 'Cannot provide both a scrollDirection and a theme.'), + childrenDelegate = SliverChildBuilderDelegate( + itemBuilder, + childCount: itemCount, + addAutomaticKeepAlives: addAutomaticKeepAlives, + addRepaintBoundaries: addRepaintBoundaries, + addSemanticIndexes: addSemanticIndexes, + ), + super( + key: key, + scrollDirection: scrollDirection ?? theme?.direction ?? Axis.vertical, + reverse: reverse, + controller: controller, + primary: primary, + physics: physics, + shrinkWrap: shrinkWrap, + padding: padding, + cacheExtent: cacheExtent, + semanticChildCount: semanticChildCount ?? itemCount, + dragStartBehavior: dragStartBehavior, + keyboardDismissBehavior: keyboardDismissBehavior, + restorationId: restorationId, + clipBehavior: clipBehavior, + ); + + /// Creates a scrollable, linear array of widgets with a custom child model. + /// + /// For example, a custom child model can control the algorithm used to + /// estimate the size of children that are not actually visible. + /// + /// See also: + /// + /// * This works similarly to [ListView.custom]. + Timeline.custom({ + required this.childrenDelegate, Key? key, + Axis? scrollDirection, + bool reverse = false, + ScrollController? controller, + bool? primary, + ScrollPhysics? physics, + bool shrinkWrap = false, + EdgeInsetsGeometry? padding, + this.itemExtent, + double? cacheExtent, + int? semanticChildCount, + DragStartBehavior dragStartBehavior = DragStartBehavior.start, + ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = + ScrollViewKeyboardDismissBehavior.manual, + String? restorationId, + Clip clipBehavior = Clip.hardEdge, + this.theme, + }) : assert(scrollDirection == null || theme == null, + 'Cannot provide both a scrollDirection and a theme.'), + super( + key: key, + scrollDirection: scrollDirection ?? theme?.direction ?? Axis.vertical, + reverse: reverse, + controller: controller, + primary: primary, + physics: physics, + shrinkWrap: shrinkWrap, + padding: padding, + cacheExtent: cacheExtent, + semanticChildCount: semanticChildCount, + dragStartBehavior: dragStartBehavior, + keyboardDismissBehavior: keyboardDismissBehavior, + restorationId: restorationId, + clipBehavior: clipBehavior, + ); + + /// If non-null, forces the children to have the given extent in the scroll + /// direction. + /// + /// Specifying an [itemExtent] is more efficient than letting the children + /// determine their own extent because the scrolling machinery can make use + /// of the foreknowledge of the children's extent to save work, for example + /// when the scroll position changes drastically. + final double? itemExtent; + + /// A delegate that provides the children for the [Timeline]. + /// + /// The [Timeline.custom] constructor lets you specify this delegate + /// explicitly. The [Timeline] and [Timeline.builder] constructors create a + /// [childrenDelegate] that wraps the given [List] and [IndexedWidgetBuilder], + /// respectively. + final SliverChildDelegate childrenDelegate; + + /// Default visual properties, like colors, size and spaces, for this + /// timeline's component widgets. + /// + /// The default value of this property is the value of + /// [TimelineThemeData.vertical()]. + final TimelineThemeData? theme; + + @override + Widget buildChildLayout(BuildContext context) { + Widget result; + if (itemExtent != null) { + result = SliverFixedExtentList( + delegate: childrenDelegate, + itemExtent: itemExtent!, + ); + } else { + result = SliverList(delegate: childrenDelegate); + } + + TimelineThemeData? theme; + if (this.theme != null) { + theme = this.theme; + } else if (scrollDirection != TimelineTheme.of(context).direction) { + theme = TimelineTheme.of(context).copyWith(direction: scrollDirection); + } + + if (theme != null) { + return TimelineTheme( + data: theme, + child: result, + ); + } else { + return result; + } + } +} + +/// A widget that displays its children in a one-dimensional array with +/// timeline theme. +class FixedTimeline extends StatelessWidget { + /// Creates a timeline flex layout. + factory FixedTimeline.tileBuilder({ + required TimelineTileBuilder builder, + TimelineThemeData? theme, + Axis? direction, + MainAxisSize mainAxisSize = MainAxisSize.max, + TextDirection? textDirection, + VerticalDirection verticalDirection = VerticalDirection.down, + Clip clipBehavior = Clip.none, + }) => + // TODO: how remove Builders? + FixedTimeline( + children: [ + for (int i = 0; i < builder.itemCount; i++) + Builder( + builder: (BuildContext context) => builder.build(context, i), + ), + ], + theme: theme, + direction: direction, + mainAxisSize: mainAxisSize, + textDirection: textDirection, + verticalDirection: verticalDirection, + clipBehavior: clipBehavior, + ); + + /// Creates a timeline flex layout. + /// + /// The [direction], [verticalDirection] arguments must not be null. + /// + /// The [textDirection] argument defaults to the ambient [Directionality], + /// if any. If there is no ambient directionality, and a text direction is + /// going to be necessary to decide which direction to lay the children in or + /// to disambiguate `start` or `end` values for the main or cross axis + /// directions, the [textDirection] must not be null. + const FixedTimeline({ + Key? key, + this.theme, + this.direction, + this.mainAxisSize = MainAxisSize.max, + this.textDirection, + this.verticalDirection = VerticalDirection.down, + this.clipBehavior = Clip.none, + this.children = const [], + }) : assert(direction == null || theme == null, + 'Cannot provide both a direction and a theme.'), + super(key: key); + + /// Default visual properties, like colors, size and spaces, for this + /// timeline's component widgets. + /// + /// The default value of this property is the value of + /// [TimelineThemeData.vertical()]. + final TimelineThemeData? theme; + + /// The direction to use as the main axis. + final Axis? direction; + + /// The widgets below this widget in the tree. + /// + /// If this list is going to be mutated, it is usually wise to put a [Key] on + /// each of the child widgets, so that the framework can match old + /// configurations to new configurations and maintain the underlying + /// render objects. + /// + /// See also: + /// + /// * [MultiChildRenderObjectWidget.children] + final List children; + + /// How much space should be occupied in the main axis. + /// + /// After allocating space to children, there might be some remaining free + /// space. This value controls whether to maximize or minimize the amount of + /// free space, subject to the incoming layout constraints. + /// + /// If some children have a non-zero flex factors (and none have a fit of + /// [FlexFit.loose]), they will expand to consume all the available space and + /// there will be no remaining free space to maximize or minimize, making this + /// value irrelevant to the final layout. + final MainAxisSize mainAxisSize; + + /// Determines the order to lay children out horizontally and how to interpret + /// `start` and `end` in the horizontal direction. + /// + /// Defaults to the ambient [Directionality]. + /// + /// If [textDirection] is [TextDirection.rtl], then the direction in which + /// text flows starts from right to left. Otherwise, if [textDirection] is + /// [TextDirection.ltr], then the direction in which text flows starts from + /// left to right. + /// + /// If the [direction] is [Axis.horizontal], this controls the order in which + /// the children are positioned (left-to-right or right-to-left). + /// + /// If the [direction] is [Axis.horizontal], and there's more than one child, + /// then the [textDirection] (or the ambient [Directionality]) must not + /// be null. + final TextDirection? textDirection; + + /// Determines the order to lay children out vertically and how to interpret + /// `start` and `end` in the vertical direction. + /// + /// Defaults to [VerticalDirection.down]. + /// + /// If the [direction] is [Axis.vertical], there's more than one child, then + /// the [verticalDirection] must not be null. + final VerticalDirection verticalDirection; + + /// The content will be clipped (or not) according to this option. + /// + /// See the enum Clip for details of all possible options and their common + /// use cases. + /// + /// Defaults to [Clip.none]. + final Clip clipBehavior; + + @override + Widget build(BuildContext context) { + final Axis direction = + this.direction ?? this.theme?.direction ?? Axis.vertical; + + final Widget result = Flex( + direction: direction, + children: children, + mainAxisSize: mainAxisSize, + textDirection: textDirection, + verticalDirection: verticalDirection, + clipBehavior: clipBehavior, + ); + + TimelineThemeData? theme; + if (this.direction != null) { + if (direction != TimelineTheme.of(context).direction) { + theme = TimelineTheme.of(context).copyWith(direction: this.direction); + } + } else if (this.theme != null) { + theme = this.theme; + } + + if (theme != null) { + return TimelineTheme( + data: theme, + child: result, + ); + } else { + return result; + } + } +} diff --git a/packages/deriv_ui/lib/components/timeline/src/util.dart b/packages/deriv_ui/lib/components/timeline/src/util.dart new file mode 100644 index 000000000..e331f567a --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/src/util.dart @@ -0,0 +1,2 @@ + +const double kFlexMultiplier = 1000; diff --git a/packages/deriv_ui/lib/components/timeline/timelines.dart b/packages/deriv_ui/lib/components/timeline/timelines.dart new file mode 100644 index 000000000..1b65013cb --- /dev/null +++ b/packages/deriv_ui/lib/components/timeline/timelines.dart @@ -0,0 +1,12 @@ +/// Widgets that make it easy to implement the timeline UI component. +library timelines; + +export 'src/connector_theme.dart'; +export 'src/connectors.dart'; +export 'src/indicator_theme.dart'; +export 'src/indicators.dart'; +export 'src/timelines.dart'; +export 'src/timeline_node.dart'; +export 'src/timeline_theme.dart'; +export 'src/timeline_tile.dart'; +export 'src/timeline_tile_builder.dart'; diff --git a/packages/deriv_ui/pubspec.yaml b/packages/deriv_ui/pubspec.yaml index 08fa0368b..acdf81391 100644 --- a/packages/deriv_ui/pubspec.yaml +++ b/packages/deriv_ui/pubspec.yaml @@ -1,6 +1,6 @@ name: deriv_ui description: A new Flutter package project. -version: 0.0.7+9 +version: 0.0.8+1 publish_to: none environment: diff --git a/packages/deriv_widgetbook/CHANGELOG.md b/packages/deriv_widgetbook/CHANGELOG.md index 5163095e0..da7b68d4c 100644 --- a/packages/deriv_widgetbook/CHANGELOG.md +++ b/packages/deriv_widgetbook/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.0.2+11 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 0.0.2+10 + + - Update a dependency to the latest release. + ## 0.0.2+9 - Update a dependency to the latest release. diff --git a/packages/deriv_widgetbook/pubspec.yaml b/packages/deriv_widgetbook/pubspec.yaml index 79424c1a1..919c759af 100644 --- a/packages/deriv_widgetbook/pubspec.yaml +++ b/packages/deriv_widgetbook/pubspec.yaml @@ -1,7 +1,7 @@ name: deriv_widgetbook description: Storybook for Deriv UI widgets and components. publish_to: "none" -version: 0.0.2+9 +version: 0.0.2+11 environment: sdk: ">=3.0.0 <4.0.0" @@ -16,7 +16,7 @@ dependencies: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git path: packages/deriv_ui - ref: deriv_ui-v0.0.7+9 + ref: deriv_ui-v0.0.8+1 deriv_theme: git: url: git@github.com:regentmarkets/flutter-deriv-packages.git diff --git a/packages/update_checker/CHANGELOG.md b/packages/update_checker/CHANGELOG.md index caf0d3f95..9d0d5fc46 100644 --- a/packages/update_checker/CHANGELOG.md +++ b/packages/update_checker/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.5.1 + + - **REFACTOR**(deriv_localizations): Crowdin Localization Generated ([#686](https://github.com/regentmarkets/flutter-deriv-packages/issues/686)). ([a0a6df21](https://github.com/regentmarkets/flutter-deriv-packages/commit/a0a6df21cbc6681b923ec3e060752de20ddad32b)) + +## 1.5.0 + + - **FEAT**(deriv_ui): [DERG 2450] Added Timeline Widget to Deriv UI ([#631](https://github.com/regentmarkets/flutter-deriv-packages/issues/631)). ([e34d78b3](https://github.com/regentmarkets/flutter-deriv-packages/commit/e34d78b303358cb5f91abab14a2a042ce3650b0f)) + ## 1.4.0 - **FEAT**(update_checker): add the ability to change the key from the app side ([#628](https://github.com/regentmarkets/flutter-deriv-packages/issues/628)). ([b18609a0](https://github.com/regentmarkets/flutter-deriv-packages/commit/b18609a00533aaab6d6962eb89f323e2f560df8b)) diff --git a/packages/update_checker/example/lib/update_bloc_page.dart b/packages/update_checker/example/lib/update_bloc_page.dart index 55b0b079f..761cc61a6 100644 --- a/packages/update_checker/example/lib/update_bloc_page.dart +++ b/packages/update_checker/example/lib/update_bloc_page.dart @@ -10,7 +10,7 @@ class UpdateBlocPage extends StatefulWidget { class _UpdateBlocPageState extends State { final UpdateBloc updateBloc = - UpdateBloc(firebaseRepository: const FirebaseRemoteConfigRepository()); + UpdateBloc(firebaseRepository: FirebaseRemoteConfigRepository()); @override Widget build(BuildContext context) => Scaffold( diff --git a/packages/update_checker/example/lib/update_checker_page.dart b/packages/update_checker/example/lib/update_checker_page.dart index 1d54f4043..672a432a0 100644 --- a/packages/update_checker/example/lib/update_checker_page.dart +++ b/packages/update_checker/example/lib/update_checker_page.dart @@ -10,7 +10,7 @@ class UpdateCheckerPage extends StatelessWidget { ), body: Builder( builder: (BuildContext context) => UpdateChecker( - firebaseRepository: const FirebaseRemoteConfigRepository(), + firebaseRepository: FirebaseRemoteConfigRepository(), onNotAvailable: () => _showSnackBar( context, 'Update not available', diff --git a/packages/update_checker/pubspec.yaml b/packages/update_checker/pubspec.yaml index 5d50c0fc9..ac5909996 100644 --- a/packages/update_checker/pubspec.yaml +++ b/packages/update_checker/pubspec.yaml @@ -1,6 +1,6 @@ name: update_checker description: Check and retrieve update information from the server for the given package. -version: 1.4.0 +version: 1.5.1 homepage: https://deriv.com/ publish_to: "none"