├── .github └── workflows │ ├── checkout.yml │ └── deploy.yml ├── .gitignore ├── .img ├── logo.ai ├── logo.png └── logo.svg ├── .vscode └── launch.json ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── analysis_options.yaml ├── example.png ├── example └── main.dart ├── lib ├── platform_info.dart └── src │ ├── base_host_platform.dart │ ├── constants.dart │ ├── default_host_platform.dart │ ├── enums.dart │ ├── js_host_platform.dart │ ├── methods.dart │ ├── platform.dart │ ├── stub_host_platform.dart │ └── vm_host_platform.dart ├── pubspec.yaml └── test └── test.dart /.github/workflows/checkout.yml: -------------------------------------------------------------------------------- 1 | name: CHECKOUT 2 | 3 | on: 4 | workflow_dispatch: 5 | #push: 6 | # branches: 7 | # - "master" 8 | # - "develop" 9 | # - "feature/**" 10 | # - "bugfix/**" 11 | # - "hotfix/**" 12 | # - "support/**" 13 | # paths: 14 | # - ".github/workflows/*.yml" 15 | # - "lib/pubspec.yaml" 16 | # - "lib/**.dart" 17 | # - "test/**.dart" 18 | # - "example/**.dart" 19 | pull_request: 20 | branches: 21 | - "master" 22 | - "develop" 23 | - "feature/**" 24 | - "bugfix/**" 25 | - "hotfix/**" 26 | - "support/**" 27 | paths: 28 | - ".github/workflows/*.yml" 29 | - "lib/pubspec.yaml" 30 | - "lib/**.dart" 31 | - "test/**.dart" 32 | - "example/**.dart" 33 | 34 | jobs: 35 | checkout: 36 | name: "Checkout" 37 | runs-on: ubuntu-latest 38 | defaults: 39 | run: 40 | working-directory: ./ 41 | container: 42 | image: dart:stable 43 | env: 44 | pub-cache-name: pub 45 | threshold: 95 46 | timeout-minutes: 10 47 | steps: 48 | - name: 🚂 Get latest code 49 | id: checkout 50 | uses: actions/checkout@v4 51 | with: 52 | sparse-checkout: | 53 | .github 54 | pubspec.yaml 55 | lib 56 | test 57 | analysis_options.yaml 58 | CHANGELOG.md 59 | 60 | - name: 📤 Restore Pub modules 61 | id: cache-pub-restore 62 | uses: actions/cache/restore@v4 63 | with: 64 | path: | 65 | $HOME/.pub-cache 66 | key: ${{ runner.os }}-${{ env.pub-cache-name }}-${{ hashFiles('**/pubspec.yaml') }} 67 | 68 | - name: 🗄️ Export Pub cache directory 69 | id: export-pub-cache 70 | timeout-minutes: 1 71 | run: | 72 | export PUB_CACHE=$PWD/.pub_cache/ 73 | export PATH="$PATH":"$HOME/.pub-cache/bin" 74 | echo "${HOME}/.pub-cache/bin" >> $GITHUB_PATH 75 | 76 | - name: 👷 Install Dependencies 77 | id: install-dependencies 78 | timeout-minutes: 1 79 | run: | 80 | apt-get update && apt-get install -y lcov 81 | dart pub global activate coverage 82 | dart pub get --no-example 83 | 84 | - name: 📥 Save Pub modules 85 | id: cache-pub-save 86 | uses: actions/cache/save@v4 87 | with: 88 | path: | 89 | $HOME/.pub-cache 90 | key: ${{ runner.os }}-${{ env.pub-cache-name }}-${{ hashFiles('**/pubspec.yaml') }} 91 | 92 | - name: 🔎 Check format 93 | id: check-format 94 | timeout-minutes: 1 95 | run: dart format --set-exit-if-changed -l 80 -o none lib/ 96 | 97 | - name: 📈 Check analyzer 98 | id: check-analyzer 99 | timeout-minutes: 1 100 | run: dart analyze --fatal-infos --fatal-warnings lib/ 101 | 102 | - name: 👀 Verify versions 103 | id: verify-versions 104 | timeout-minutes: 1 105 | run: | 106 | test -f pubspec.yaml && test -f CHANGELOG.md 107 | version_pubspec=$(grep '^version:' pubspec.yaml | awk '{print $2}' | sed 's/[^[:print:]]//g') 108 | test -n "$version_pubspec" 109 | echo "Version from pubspec.yaml: '$version_pubspec'" 110 | grep -q "# $version_pubspec" CHANGELOG.md || (echo "Version not found in CHANGELOG.md" >&2; exit 1) 111 | 112 | #- name: Check with pana 113 | # run: dart pub global activate pana && pana --json --no-warning --line-length 80 114 | 115 | - name: 🧪 Run tests 116 | id: run-tests 117 | timeout-minutes: 2 118 | run: | 119 | dart pub global run coverage:test_with_coverage -fb -o coverage -- \ 120 | --platform vm --compiler=kernel --coverage=coverage \ 121 | --reporter=github --file-reporter=json:coverage/tests.json \ 122 | --timeout=10m --concurrency=12 --color \ 123 | test/test.dart 124 | 125 | - name: 🔍 Check coverage 126 | id: check-coverage 127 | timeout-minutes: 2 128 | run: | 129 | mv coverage/lcov.info coverage/lcov.base.info 130 | lcov --remove coverage/lcov.base.info '*.g.dart' -o coverage/lcov.info 131 | lcov --list coverage/lcov.info 132 | THRESHOLD=${{ env.threshold }} 133 | COVERAGE=$(lcov --summary coverage/lcov.info | grep -i 'lines\|Total:' | tail -n 1 | awk '{print $2}' | sed 's/%//') 134 | echo "Coverage is $COVERAGE%" 135 | echo $COVERAGE | awk '{if ($1 < 50) exit 1}' 136 | 137 | - name: 🧹 Cleanup artifacts 138 | id: cleanup-artifacts 139 | if: always() 140 | timeout-minutes: 2 141 | run: | 142 | rm -rf ~/build 143 | 144 | - name: ✨ Upload coverage to Codecov 145 | id: upload-coverage 146 | timeout-minutes: 2 147 | uses: codecov/codecov-action@v4 148 | with: 149 | token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos 150 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "[0-9]+.[0-9]+.[0-9]+*" 8 | 9 | jobs: 10 | deploy: 11 | name: "Deploy to Pub.dev" 12 | permissions: 13 | id-token: write # Required for authentication using OIDC 14 | uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don’t commit the following directories created by pub. 2 | .buildlog 3 | .dart_tool/ 4 | .pub/ 5 | build/ 6 | packages 7 | *.packages 8 | .idea/ 9 | web/experimental 10 | doc 11 | 12 | # Or the files created by dart2js. 13 | *.dart.js 14 | *.js_ 15 | *.js.deps 16 | *.js.map 17 | 18 | # Include when developing application packages. 19 | pubspec.lock 20 | coverage* 21 | 22 | # Test 23 | .coverage/ 24 | /test/**/*.json 25 | /test/.test_coverage.dart 26 | log.pana.json -------------------------------------------------------------------------------- /.img/logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlugFox/platform_info/4c6fb44c537da11964ac2ea00c318b385e335dfe/.img/logo.ai -------------------------------------------------------------------------------- /.img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlugFox/platform_info/4c6fb44c537da11964ac2ea00c318b385e335dfe/.img/logo.png -------------------------------------------------------------------------------- /.img/logo.svg: -------------------------------------------------------------------------------- 1 | logo[ ] -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Example", 9 | "request": "launch", 10 | "type": "dart", 11 | "program": "example/main.dart", 12 | "args": [] 13 | }, 14 | // https://pub.dev/packages/test 15 | // dart test test/ws_test.dart --color --platform=vm 16 | { 17 | "name": "Test (VM)", 18 | "request": "launch", 19 | "type": "dart", 20 | "program": "test/platform_info_test.dart", 21 | "env": { 22 | "ENVIRONMENT": "test" 23 | }, 24 | "console": "debugConsole", 25 | "runTestsOnDevice": false, 26 | "templateFor": "test", 27 | "toolArgs": [ 28 | "--color", 29 | "--debug", 30 | "--coverage=.coverage", 31 | "--reporter=expanded", 32 | "--platform=vm", // chrome 33 | "--file-reporter=json:.coverage/tests.json", 34 | "--timeout=30s", 35 | "--concurrency=12" 36 | ], 37 | "args": [] 38 | }, 39 | // dart test test/ws_test.dart --color --platform=chrome 40 | { 41 | "name": "Test (Browser)", 42 | "request": "launch", 43 | "type": "dart", 44 | "program": "test/platform_info_test.dart", 45 | "env": { 46 | "ENVIRONMENT": "test" 47 | }, 48 | "console": "debugConsole", 49 | "runTestsOnDevice": false, 50 | "templateFor": "test", 51 | "toolArgs": [ 52 | "--color", 53 | "--debug", 54 | "--coverage=.coverage", 55 | "--reporter=expanded", 56 | "--platform=chrome", 57 | "--file-reporter=json:.coverage/tests.json", 58 | "--timeout=30s", 59 | "--concurrency=12" 60 | ], 61 | "args": [] 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 5.0.0 - 2024-08-13 2 | 3 | - Update dependencies 4 | - dart:html replaced with package:web 5 | - Enums replaced with sealed classes 6 | - Renamed getters 7 | 8 | ## 4.0.2 - 2023-06-30 9 | 10 | - Fix topics 11 | 12 | ## 4.0.1 - 2023-06-30 13 | 14 | - Update README.md 15 | - Refactoring 16 | 17 | ## 4.0.0 - 2023-05-13 18 | 19 | ### Changed 20 | 21 | - Dart 3.0.0 ready 22 | 23 | ## 3.2.0 - 2022-05-19 24 | 25 | ### Fixed 26 | 27 | - Linux is desktop platform now 28 | 29 | ## 3.1.0 - 2021-05-29 30 | 31 | ### Added 32 | 33 | - Extensions for enums BuildMode, HostPlatformType, OperatingSystem 34 | 35 | ## 3.0.0 - 2021-03-27 36 | 37 | ### Changed 38 | 39 | - Non nullable ready 40 | - Refactoring 41 | 42 | ## 3.0.0-nullsafety.2 - 2021-03-24 43 | 44 | ### Added 45 | 46 | - Add some badges 47 | 48 | ## 3.0.0-nullsafety.1 - 2021-02-19 49 | 50 | ### Changed 51 | 52 | - Non nullable ready 53 | 54 | ## 2.2.0 - 2020-11-20 55 | 56 | ### Changed 57 | 58 | - Add when feature 59 | 60 | ## 2.1.0 - 2020-10-18 61 | 62 | ### Changed 63 | 64 | - Fix `kListOSWithCupertinoDesign` constant and `cupertino` flag 65 | 66 | ## 2.0.1 - 2020-09-06 67 | 68 | ### Added 69 | 70 | - Add getters: 71 | - `isJS` - Is a web-based applications 72 | - `isVM` - Is a I/O supporting for non-web applications 73 | 74 | ## 2.0.0 - 2020-08-28 75 | 76 | ### Added 77 | 78 | - Add global getter platform 79 | - operating system check 80 | - Three short form to access the instance of Platform 81 | - `Platform.instance` 82 | - `Platform.I` 83 | - `platform` 84 | 85 | ### Changed 86 | 87 | - refactoring and new lints (pedantic + effective dart) 88 | 89 | ### Removed 90 | 91 | - Removed toJson() method from Platform 92 | - Remove default factory Platform() 93 | 94 | ## 1.1.1+3 - 2020-04-25 95 | 96 | ### Changed 97 | 98 | - Fix analysis options 99 | 100 | ## 1.1.1+2 - 2020-04-25 101 | 102 | ### Removed 103 | 104 | - Disable most dev dependencies 105 | 106 | ## 1.1.1+1 - 2020-04-23 107 | 108 | ### Added 109 | 110 | - Add logo image 111 | 112 | ## 1.1.1 - 2020-04-23 113 | 114 | ### Added 115 | 116 | - Cashed flags 117 | - Add toJson() method 118 | 119 | ## 1.1.0 - 2020-04-23 120 | 121 | ### Added 122 | 123 | - Add new flags: 124 | - desktop 125 | - material 126 | - cupertino 127 | 128 | ## 1.0.1 - 2020-04-22 129 | 130 | ### Changed 131 | 132 | - Update badge and readme 133 | 134 | ## 1.0.0 - 2020-04-22 135 | 136 | ### Added 137 | 138 | - Initial Version of the library. 139 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 2023 Matiunin Mikhail 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: format get upgrade outdated analyze deploy coverage 2 | 3 | format: 4 | @echo "Formatting the code" 5 | @dart format -l 80 --fix . 6 | @dart fix --apply . 7 | 8 | get: 9 | @echo "Geting dependencies" 10 | @dart pub get 11 | 12 | upgrade: get 13 | @echo "Upgrading dependencies" 14 | @dart pub upgrade 15 | 16 | outdated: 17 | @echo "Outdated check" 18 | @dart pub outdated 19 | 20 | analyze: get format 21 | @echo "Analyze the code" 22 | @dart analyze --fatal-infos --fatal-warnings 23 | 24 | check: analyze 25 | @dart pub publish --dry-run 26 | @dart pub global activate pana 27 | @pana --json --no-warning --line-length 80 > log.pana.json 28 | 29 | pana: check 30 | 31 | deploy: 32 | @echo "Publish" 33 | @dart pub publish 34 | 35 | coverage: get 36 | @dart test --concurrency=6 --platform vm --coverage=coverage test/ 37 | @dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib 38 | # @mv coverage/lcov.info coverage/lcov.base.info 39 | # @lcov -r coverage/lcov.base.info -o coverage/lcov.base.info "lib/**.freezed.dart" "lib/**.g.dart" 40 | # @mv coverage/lcov.base.info coverage/lcov.info 41 | @lcov --list coverage/lcov.info 42 | @genhtml -o coverage coverage/lcov.info 43 | 44 | test: get 45 | @dart test --debug --coverage=.coverage --platform chrome,vm -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # platform_info 2 | 3 | [![platform_info](https://img.shields.io/pub/v/platform_info.svg)](https://pub.dev/packages/platform_info) 4 | [![Checkout](https://github.com/PlugFox/platform_info/actions/workflows/checkout.yml/badge.svg)](https://github.com/PlugFox/platform_info/actions/workflows/checkout.yml) 5 | [![Coverage](https://codecov.io/gh/PlugFox/platform_info/branch/master/graph/badge.svg)](https://codecov.io/gh/PlugFox/platform_info) 6 | [![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](https://opensource.org/licenses/MIT) 7 | [![Linter](https://img.shields.io/badge/style-linter-40c4ff.svg)](https://pub.dev/packages/linter) 8 | [![GitHub stars](https://img.shields.io/github/stars/plugfox/platform_info?style=social)](https://github.com/plugfox/platform_info/) 9 | 10 | ## About 11 | 12 | Cross-platform io/html package. 13 | Works on the web, mobile phones, desktops and console. 14 | Fully caches itself on first initialization. 15 | 16 | Easy to use, just add to `pubspec.yaml` as dependency and then import: 17 | `import 'package:platform_info/platform_info.dart';` 18 | 19 | Platform is a singleton, and the default way to access an instance of Platform is to call static getters: 20 | `Platform.instance` or `Platform.I` or `platform` 21 | 22 | ## Usage 23 | 24 | ![](example.png) 25 | [Example of using the library](https://pub.dev/packages/platform_info/example) to get the current platform info 26 | 27 | ## Platform Information 28 | 29 | Provides platform information such as: 30 | 31 | - Build mode 32 | 33 | - release 34 | - profile 35 | - debug 36 | 37 | - Host platform type 38 | 39 | - vm (io, desktops, mobile, console, server) 40 | - js (web, html, browser) 41 | 42 | - Operating system 43 | 44 | - Fuchsia 45 | - Linux 46 | - MacOS 47 | - Windows 48 | - iOS 49 | - Android 50 | - Unknown 51 | 52 | - Version (`unknown` if not available) 53 | 54 | - Locale string (`en` if not available) 55 | 56 | - The number of individual execution units of the machine (`0` if not available) 57 | 58 | - Operating system is a known type 59 | 60 | - Is a Web-based applications 61 | 62 | - Is a VM supporting for non-web applications 63 | 64 | - Is a mobile device (Android, iOS) 65 | 66 | - Is a desktop device (Windows, macOS, Fuchsia) 67 | 68 | - Is Material design device (Android, Fuchsia) 69 | 70 | - Is Cupertino design device (macOS, iOS) 71 | 72 | - is Linux 73 | 74 | - is macOS 75 | 76 | - is Windows 77 | 78 | - is android 79 | 80 | - is iOS 81 | 82 | - is fuchsia 83 | 84 | - `when` method allowing to compose a complex condition 85 | 86 | ## Pattern matching 87 | 88 | Run functions that satisfy the current state of the platform. 89 | You can use nested methods to compose more complex queries. 90 | 91 | ##### Operating System 92 | 93 | [fuchsia] - whether the operating system is a version of Fuchsia 94 | [windows] - whether the operating system is a version of Windows 95 | [android] - whether the operating system is a version of Android 96 | [iOS] - whether the operating system is a version of iOS 97 | [macOS] - whether the operating system is a version of MacOS 98 | [linux] - whether the operating system is a version of Linux 99 | [unknown] - operating system unknown 100 | 101 | ##### Design 102 | 103 | [material] - is material (Android, Fuchsia) 104 | [cupertino] - is cupertino (macOS, iOS) 105 | 106 | ##### Mobile or desktop 107 | 108 | [mobile] - is mobile device (Android, iOS) 109 | [desktop] - is desktop device (Windows, MacOS, Fuchsia) 110 | 111 | ##### VM (IO) or JS (Web) 112 | 113 | [js] - is web-based applications 114 | [vm] - is I/O supporting for non-web applications 115 | 116 | ##### Build mode 117 | 118 | [release] - release build mode 119 | [profile] - profile build mode 120 | [debug] - debug build mode 121 | [orElse] - any callback was not called 122 | 123 | ##### Sequence of checks 124 | 125 | 1. Operating System 126 | 2. Design 127 | 3. Mobile/Desktop 128 | 4. VM/JS 129 | 5. Build mode 130 | 6. Call [orElse] if any callback was not called 131 | 132 | ## Coverage 133 | 134 | [![](https://codecov.io/gh/PlugFox/platform_info/branch/master/graphs/sunburst.svg)](https://codecov.io/gh/PlugFox/platform_info/branch/master) 135 | 136 | ## Changelog 137 | 138 | Refer to the [Changelog](https://github.com/plugfox/platform_info/blob/master/CHANGELOG.md) to get all release notes. 139 | 140 | ## Maintainers 141 | 142 | [Plague Fox](https://plugfox.dev) 143 | 144 | ## Funding 145 | 146 | If you want to support the development of our library, there are several ways you can do it: 147 | 148 | - [Buy me a coffee](https://www.buymeacoffee.com/plugfox) 149 | - [Support on Patreon](https://www.patreon.com/plugfox) 150 | - [Subscribe through Boosty](https://boosty.to/plugfox) 151 | 152 | We appreciate any form of support, whether it's a financial donation or just a star on GitHub. It helps us to continue developing and improving our library. Thank you for your support! 153 | 154 | ## License 155 | 156 | [MIT](https://opensource.org/licenses/MIT) 157 | 158 | ## Tags 159 | 160 | cross, platform, info 161 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Customizing static analysis 2 | # https://dart.dev/guides/language/analysis-options/ 3 | # https://dart-lang.github.io/linter/lints/ 4 | 5 | include: package:lints/recommended.yaml 6 | 7 | analyzer: 8 | exclude: 9 | # Web 10 | - 'web/**' 11 | # Build 12 | - 'build/**' 13 | # Assets 14 | - 'assets/**' 15 | # Mocks for test 16 | - 'test/data/**' 17 | # Coverage 18 | - 'test/.test_coverage.dart' 19 | 20 | # Enable the following options to enable strong mode. 21 | language: 22 | strict-casts: true 23 | strict-raw-types: true 24 | strict-inference: true 25 | 26 | #enable-experiment: 27 | # - non-nullable 28 | 29 | errors: 30 | # Info 31 | todo: info 32 | directives_ordering: info 33 | always_declare_return_types: info 34 | 35 | # Warning 36 | unsafe_html: warning 37 | prefer_relative_imports: warning 38 | no_logic_in_create_state: warning 39 | empty_catches: warning 40 | 41 | # Error 42 | avoid_relative_lib_imports: error 43 | avoid_slow_async_io: error 44 | avoid_types_as_parameter_names: error 45 | cancel_subscriptions: error 46 | close_sinks: error 47 | valid_regexps: error 48 | always_require_non_null_named_parameters: error 49 | 50 | linter: 51 | rules: 52 | # Package 53 | lines_longer_than_80_chars: true 54 | public_member_api_docs: true 55 | 56 | # Disabled 57 | always_specify_types: false 58 | avoid_as: false 59 | avoid_redundant_argument_values: false 60 | comment_references: false # Unused because https://github.com/dart-lang/sdk/issues/36974 61 | prefer_double_quotes: false 62 | sort_constructors_first: false 63 | sort_unnamed_constructors_first: false 64 | use_key_in_widget_constructors: false 65 | always_put_control_body_on_new_line: false 66 | #diagnostic_describe_all_properties: false # ??? 67 | 68 | # Enabled 69 | always_put_required_named_parameters_first: true 70 | avoid_annotating_with_dynamic: true 71 | avoid_bool_literals_in_conditional_expressions: true 72 | avoid_double_and_int_checks: true 73 | avoid_escaping_inner_quotes: true 74 | avoid_field_initializers_in_const_classes: true 75 | avoid_implementing_value_types: true 76 | avoid_js_rounded_ints: true 77 | avoid_print: true 78 | avoid_renaming_method_parameters: true 79 | avoid_returning_null_for_future: true 80 | avoid_returning_null_for_void: true 81 | avoid_single_cascade_in_expression_statements: true 82 | avoid_slow_async_io: true 83 | avoid_unnecessary_containers: true 84 | avoid_unused_constructor_parameters: true 85 | avoid_void_async: true 86 | await_only_futures: true 87 | cancel_subscriptions: true 88 | cascade_invocations: true 89 | close_sinks: true 90 | control_flow_in_finally: true 91 | empty_statements: true 92 | iterable_contains_unrelated_type: true 93 | join_return_with_assignment: true 94 | leading_newlines_in_multiline_strings: true 95 | list_remove_unrelated_type: true 96 | literal_only_boolean_expressions: true 97 | missing_whitespace_between_adjacent_strings: true 98 | no_adjacent_strings_in_list: true 99 | no_logic_in_create_state: true 100 | no_runtimeType_toString: true 101 | only_throw_errors: true 102 | overridden_fields: true 103 | package_names: true 104 | package_prefixed_library_names: true 105 | parameter_assignments: true 106 | prefer_asserts_in_initializer_lists: true 107 | prefer_asserts_with_message: true 108 | prefer_const_constructors: true 109 | prefer_const_constructors_in_immutables: true 110 | prefer_const_declarations: true 111 | prefer_const_literals_to_create_immutables: true 112 | prefer_constructors_over_static_methods: true 113 | prefer_expression_function_bodies: true 114 | prefer_final_in_for_each: true 115 | prefer_final_locals: true 116 | prefer_foreach: true 117 | prefer_if_elements_to_conditional_expressions: true 118 | prefer_inlined_adds: true 119 | prefer_int_literals: true 120 | prefer_is_not_operator: true 121 | prefer_null_aware_operators: true 122 | prefer_typing_uninitialized_variables: true 123 | prefer_void_to_null: true 124 | provide_deprecation_message: true 125 | sized_box_for_whitespace: true 126 | sort_child_properties_last: true 127 | sort_pub_dependencies: true 128 | test_types_in_equals: true 129 | throw_in_finally: true 130 | unnecessary_null_aware_assignments: true 131 | unnecessary_overrides: true 132 | unnecessary_parenthesis: true 133 | unnecessary_raw_strings: true 134 | unnecessary_statements: true 135 | unnecessary_string_escapes: true 136 | unnecessary_string_interpolations: true 137 | unsafe_html: true 138 | use_raw_strings: true 139 | use_string_buffers: true 140 | valid_regexps: true 141 | void_checks: true 142 | 143 | # Pedantic 1.9.0 144 | always_declare_return_types: true 145 | always_require_non_null_named_parameters: true 146 | annotate_overrides: true 147 | avoid_empty_else: true 148 | avoid_init_to_null: true 149 | avoid_null_checks_in_equality_operators: true 150 | avoid_relative_lib_imports: true 151 | avoid_return_types_on_setters: true 152 | avoid_shadowing_type_parameters: true 153 | avoid_types_as_parameter_names: true 154 | camel_case_extensions: true 155 | curly_braces_in_flow_control_structures: true 156 | empty_catches: true 157 | empty_constructor_bodies: true 158 | library_names: true 159 | library_prefixes: true 160 | no_duplicate_case_values: true 161 | null_closures: true 162 | omit_local_variable_types: true 163 | prefer_adjacent_string_concatenation: true 164 | prefer_collection_literals: true 165 | prefer_conditional_assignment: true 166 | prefer_contains: true 167 | prefer_final_fields: true 168 | prefer_for_elements_to_map_fromIterable: true 169 | prefer_generic_function_type_aliases: true 170 | prefer_if_null_operators: true 171 | prefer_is_empty: true 172 | prefer_is_not_empty: true 173 | prefer_iterable_whereType: true 174 | prefer_single_quotes: true 175 | prefer_spread_collections: true 176 | recursive_getters: true 177 | slash_for_doc_comments: true 178 | type_init_formals: true 179 | unawaited_futures: true 180 | unnecessary_const: true 181 | unnecessary_new: true 182 | unnecessary_null_in_if_null_operators: true 183 | unnecessary_this: true 184 | unrelated_type_equality_checks: true 185 | use_function_type_syntax_for_parameters: true 186 | use_rethrow_when_possible: true 187 | 188 | # Effective_dart 1.2.0 189 | camel_case_types: true 190 | file_names: true 191 | non_constant_identifier_names: true 192 | constant_identifier_names: true 193 | directives_ordering: true 194 | package_api_docs: true 195 | implementation_imports: true 196 | prefer_relative_imports: true 197 | prefer_interpolation_to_compose_strings: true 198 | unnecessary_brace_in_string_interps: true 199 | avoid_function_literals_in_foreach_calls: true 200 | prefer_function_declarations_over_variables: true 201 | unnecessary_lambdas: true 202 | unnecessary_getters_setters: true 203 | prefer_initializing_formals: true 204 | avoid_catches_without_on_clauses: true 205 | avoid_catching_errors: true 206 | use_to_and_as_if_applicable: true 207 | one_member_abstracts: true 208 | avoid_classes_with_only_static_members: true 209 | prefer_mixin: true 210 | use_setters_to_change_properties: true 211 | avoid_setters_without_getters: true 212 | avoid_returning_null: true 213 | avoid_returning_this: true 214 | type_annotate_public_apis: true 215 | avoid_types_on_closure_parameters: true 216 | avoid_private_typedef_functions: true 217 | avoid_positional_boolean_parameters: true 218 | hash_and_equals: true 219 | avoid_equals_and_hash_code_on_mutable_classes: true 220 | -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlugFox/platform_info/4c6fb44c537da11964ac2ea00c318b385e335dfe/example.png -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_print 2 | 3 | import 'package:platform_info/platform_info.dart'; 4 | 5 | void main(List args) { 6 | // Use [Platform.instance] or [Platform.I] or [platform] getter 7 | print(Platform.instance.version); 8 | print(Platform.I.operatingSystem); 9 | print(platform.numberOfProcessors); 10 | 11 | final design = platform.when( 12 | vm: () => platform.when( 13 | material: () => 'Android or Fuchsia', 14 | cupertino: () => 'macOS or iOS', 15 | orElse: () => 'Windows or Linux', 16 | ), 17 | js: () => 'Web', 18 | ); 19 | print(design); 20 | 21 | final operatingSystem = switch (platform.operatingSystem) { 22 | const OperatingSystem.android() => 'Android', 23 | const OperatingSystem.fuchsia() => 'Fuchsia', 24 | const OperatingSystem.iOS() => 'iOS', 25 | const OperatingSystem.linux() => 'Linux', 26 | const OperatingSystem.macOS() => 'macOS', 27 | const OperatingSystem.windows() => 'Windows', 28 | const OperatingSystem.unknown() || _ => 'Unknown', 29 | }; 30 | print(operatingSystem); 31 | 32 | final buildMode = switch (platform.buildMode) { 33 | BuildMode$Debug _ => 'Debug', 34 | BuildMode$Profile _ => 'Profile', 35 | BuildMode$Release _ => 'Release', 36 | }; 37 | print(buildMode); 38 | } 39 | -------------------------------------------------------------------------------- /lib/platform_info.dart: -------------------------------------------------------------------------------- 1 | library platform_info; 2 | 3 | import 'src/platform.dart' show Platform; 4 | 5 | export 'src/enums.dart'; 6 | export 'src/platform.dart'; 7 | 8 | /// [Platform] info 9 | /// Works on the web, mobile phones, desktops and console. 10 | /// Provides platform information such as: 11 | /// + Build mode 12 | /// * release (release build mode) 13 | /// * profile (profile build mode) 14 | /// * debug (debug build mode) 15 | /// 16 | /// + Host platform type 17 | /// * io (desktops, mobile, console) 18 | /// * web (browser) 19 | /// 20 | /// + Operation system 21 | /// * Fuchsia 22 | /// * Linux 23 | /// * MacOS 24 | /// * Windows 25 | /// * iOS 26 | /// * Android 27 | /// * Unknown 28 | /// 29 | /// + Version 30 | /// 31 | /// + Locale string 32 | /// 33 | /// + The number of individual execution units of the machine. 34 | /// 35 | /// + Operating system is known type 36 | /// 37 | /// + Is mobile device (Android, iOS) 38 | /// 39 | /// + Is desktop device (Windows, MacOS, Fuchsia) 40 | /// 41 | /// + Is material (Android, Fuchsia) 42 | /// 43 | /// + Is cupertino (MacOS, iOS) 44 | /// 45 | /// 46 | Platform get platform => Platform.instance; 47 | -------------------------------------------------------------------------------- /lib/src/base_host_platform.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart' show immutable; 2 | 3 | import 'enums.dart'; 4 | 5 | /// Host platform 6 | /// contain info about host device 7 | @immutable 8 | abstract base class HostPlatform { 9 | /// A constant constructor to allow subclasses to be const. 10 | const HostPlatform(); 11 | 12 | /// Host platform type 13 | /// + io 14 | /// + web 15 | abstract final HostPlatformType type; 16 | 17 | /// Operation system 18 | /// + Fuchsia 19 | /// + Linux 20 | /// + MacOS 21 | /// + Windows 22 | /// + iOS 23 | /// + Android 24 | /// + Unknown 25 | abstract final OperatingSystem operatingSystem; 26 | 27 | /// Version 28 | /// in i/o - operating system version 29 | /// in Web - user agent string 30 | abstract final String version; 31 | 32 | /// Locale string 33 | abstract final String locale; 34 | 35 | /// The number of individual execution units of the machine 36 | /// Returns 0 if unknown or not available 37 | /// Use `.clamp(1, double.infinity)` if you need a quantity greater than 0 38 | abstract final int numberOfProcessors; 39 | } 40 | 41 | /// Extended host platform 42 | abstract base class ExtendedHostPlatform extends HostPlatform { 43 | /// A constant constructor to allow subclasses to be const. 44 | const ExtendedHostPlatform(); 45 | 46 | /// Is web-based applications 47 | abstract final bool js; 48 | 49 | /// Is I/O supporting for non-web applications 50 | abstract final bool vm; 51 | 52 | /// Is mobile device (Android, iOS) 53 | abstract final bool mobile; 54 | 55 | /// Is desktop device (Windows, MacOS, Fuchsia) 56 | abstract final bool desktop; 57 | 58 | /// Is material (Android, Fuchsia) 59 | abstract final bool material; 60 | 61 | /// Is cupertino (MacOS, iOS) 62 | abstract final bool cupertino; 63 | 64 | /// Whether the operating system is a version of 65 | /// [Android](https://en.wikipedia.org/wiki/Android_%28operating_system%29) 66 | abstract final bool android; 67 | 68 | /// Whether the operating system is a version of 69 | /// [Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia) 70 | abstract final bool fuchsia; 71 | 72 | /// Whether the operating system is a version of 73 | /// [iOS](https://en.wikipedia.org/wiki/IOS) 74 | abstract final bool iOS; 75 | 76 | /// Whether the operating system is a version of 77 | /// [Linux](https://en.wikipedia.org/wiki/Linux) 78 | /// 79 | /// This value is `false` if the operating system is a specialized 80 | /// version of Linux that identifies itself by a different name, 81 | /// for example Android (see [android]) 82 | abstract final bool linux; 83 | 84 | /// Whether the operating system is a version of 85 | /// [macOS](https://en.wikipedia.org/wiki/MacOS) 86 | abstract final bool macOS; 87 | 88 | /// Whether the operating system is a version of 89 | /// [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows). 90 | abstract final bool windows; 91 | 92 | /// Unknown operating system 93 | abstract final bool unknown; 94 | 95 | /// Build mode 96 | /// + release - Release build mode 97 | /// + profile - Profile build mode 98 | /// + debug - Debug build mode 99 | abstract final BuildMode buildMode; 100 | } 101 | -------------------------------------------------------------------------------- /lib/src/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | import 'base_host_platform.dart' show HostPlatform; 4 | import 'default_host_platform.dart'; 5 | import 'enums.dart'; 6 | 7 | /// Set of all mobile phone operating systems 8 | @internal 9 | final Set kListOSForMobile = { 10 | const OperatingSystem.android(), 11 | const OperatingSystem.iOS(), 12 | }; 13 | 14 | /// Set of all operating systems with material design 15 | @internal 16 | final Set kListOSWithMaterialDesign = { 17 | const OperatingSystem.android(), 18 | const OperatingSystem.fuchsia(), 19 | }; 20 | 21 | /// Set of all operating systems with cupertino design 22 | @internal 23 | final Set kListOSWithCupertinoDesign = { 24 | const OperatingSystem.macOS(), 25 | const OperatingSystem.iOS(), 26 | }; 27 | 28 | /// Set of all desktop operating systems 29 | @internal 30 | final Set kListOSForDesktop = { 31 | const OperatingSystem.windows(), 32 | const OperatingSystem.macOS(), 33 | const OperatingSystem.fuchsia(), 34 | const OperatingSystem.linux(), 35 | }; 36 | 37 | /// Unknown host platform with default values 38 | @internal 39 | const HostPlatform kDefaultHostPlatform = DefaultHostPlatform(); 40 | -------------------------------------------------------------------------------- /lib/src/default_host_platform.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart' show immutable, literal; 2 | 3 | import 'base_host_platform.dart' show HostPlatform; 4 | import 'enums.dart'; 5 | 6 | /// Unknown host platform with default values 7 | @immutable 8 | final class DefaultHostPlatform extends HostPlatform { 9 | /// Unknown host platform with default values 10 | @literal 11 | const DefaultHostPlatform(); 12 | 13 | @override 14 | HostPlatformType get type => identical(0, 0.0) 15 | ? const HostPlatformType.js() 16 | : const HostPlatformType.vm(); 17 | 18 | @override 19 | OperatingSystem get operatingSystem => const OperatingSystem.unknown(); 20 | 21 | @override 22 | String get version => 'unknown'; 23 | 24 | @override 25 | String get locale => 'en'; 26 | 27 | @override 28 | int get numberOfProcessors => 0; 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/enums.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | /// Build mode enum 4 | /// + debug - Debug build mode 5 | /// + profile - Profile build mode 6 | /// + release - Release build mode 7 | @immutable 8 | sealed class BuildMode { 9 | /// Build mode 10 | const BuildMode(); 11 | 12 | /// Build mode: debug 13 | @literal 14 | const factory BuildMode.debug() = BuildMode$Debug; 15 | 16 | /// Build mode: profile 17 | @literal 18 | const factory BuildMode.profile() = BuildMode$Profile; 19 | 20 | /// Build mode: release 21 | @literal 22 | const factory BuildMode.release() = BuildMode$Release; 23 | 24 | /// List of all build modes 25 | static const List values = [ 26 | BuildMode$Debug(), 27 | BuildMode$Profile(), 28 | BuildMode$Release(), 29 | ]; 30 | 31 | /// Is debug build mode 32 | abstract final bool debug; 33 | 34 | /// Is profile build mode 35 | abstract final bool profile; 36 | 37 | /// Is release build mode 38 | abstract final bool release; 39 | 40 | /// Run callback on specific build mode 41 | BuildModeResult when({ 42 | required BuildModeResult Function() debug, 43 | required BuildModeResult Function() profile, 44 | required BuildModeResult Function() release, 45 | }); 46 | 47 | /// Run callback on specific build mode, 48 | /// if not specified run orElse 49 | BuildModeResult maybeWhen({ 50 | required BuildModeResult Function() orElse, 51 | BuildModeResult Function()? debug, 52 | BuildModeResult Function()? profile, 53 | BuildModeResult Function()? release, 54 | }) => 55 | when( 56 | debug: debug ?? orElse, 57 | profile: profile ?? orElse, 58 | release: release ?? orElse, 59 | ); 60 | } 61 | 62 | /// Build mode: debug 63 | final class BuildMode$Debug extends BuildMode { 64 | /// Build mode: debug 65 | @literal 66 | const BuildMode$Debug(); 67 | 68 | @override 69 | BuildModeResult when({ 70 | required BuildModeResult Function() debug, 71 | required BuildModeResult Function() profile, 72 | required BuildModeResult Function() release, 73 | }) => 74 | debug(); 75 | 76 | @override 77 | bool get debug => true; 78 | 79 | @override 80 | bool get profile => false; 81 | 82 | @override 83 | bool get release => false; 84 | 85 | @override 86 | int get hashCode => 0; 87 | 88 | @override 89 | bool operator ==(Object other) => 90 | identical(this, other) || other is BuildMode$Debug; 91 | 92 | @override 93 | String toString() => 'debug'; 94 | } 95 | 96 | /// Build mode: profile 97 | final class BuildMode$Profile extends BuildMode { 98 | /// Build mode: profile 99 | @literal 100 | const BuildMode$Profile(); 101 | 102 | @override 103 | BuildModeResult when({ 104 | required BuildModeResult Function() debug, 105 | required BuildModeResult Function() profile, 106 | required BuildModeResult Function() release, 107 | }) => 108 | profile(); 109 | 110 | @override 111 | bool get debug => false; 112 | 113 | @override 114 | bool get profile => true; 115 | 116 | @override 117 | bool get release => false; 118 | 119 | @override 120 | int get hashCode => 1; 121 | 122 | @override 123 | bool operator ==(Object other) => 124 | identical(this, other) || other is BuildMode$Profile; 125 | 126 | @override 127 | String toString() => 'profile'; 128 | } 129 | 130 | /// Build mode: release 131 | final class BuildMode$Release extends BuildMode { 132 | /// Build mode: release 133 | @literal 134 | const BuildMode$Release(); 135 | 136 | @override 137 | BuildModeResult when({ 138 | required BuildModeResult Function() debug, 139 | required BuildModeResult Function() profile, 140 | required BuildModeResult Function() release, 141 | }) => 142 | release(); 143 | 144 | @override 145 | bool get debug => false; 146 | 147 | @override 148 | bool get profile => false; 149 | 150 | @override 151 | bool get release => true; 152 | 153 | @override 154 | int get hashCode => 2; 155 | 156 | @override 157 | bool operator ==(Object other) => 158 | identical(this, other) || other is BuildMode$Release; 159 | 160 | @override 161 | String toString() => 'release'; 162 | } 163 | 164 | /// Host platform type 165 | /// + io (vm, desktops, mobile, console) 166 | /// + web (html, js, browser) 167 | @immutable 168 | sealed class HostPlatformType { 169 | /// Host platform type 170 | const HostPlatformType(); 171 | 172 | /// VM (io, vm, desktops, mobile, console) 173 | @literal 174 | const factory HostPlatformType.vm() = HostPlatformType$VM; 175 | 176 | /// JS (browser, web, html, js) 177 | @literal 178 | const factory HostPlatformType.js() = HostPlatformType$JS; 179 | 180 | /// List of all host platform types 181 | static const List values = [ 182 | HostPlatformType$VM(), 183 | HostPlatformType$JS(), 184 | ]; 185 | 186 | /// Is VM (io, vm, desktops, mobile, console) 187 | abstract final bool vm; 188 | 189 | /// Is JS (browser, web, html, js) 190 | abstract final bool js; 191 | 192 | /// Run callback on specific host platform 193 | HostPlatformTypeResult when({ 194 | required HostPlatformTypeResult Function() vm, 195 | required HostPlatformTypeResult Function() js, 196 | }); 197 | } 198 | 199 | /// VM (io, vm, desktops, mobile, console) 200 | final class HostPlatformType$VM extends HostPlatformType { 201 | /// VM (io, vm, desktops, mobile, console) 202 | @literal 203 | const HostPlatformType$VM(); 204 | 205 | @override 206 | HostPlatformTypeResult when({ 207 | required HostPlatformTypeResult Function() vm, 208 | required HostPlatformTypeResult Function() js, 209 | }) => 210 | vm(); 211 | 212 | @override 213 | bool get vm => true; 214 | 215 | @override 216 | bool get js => false; 217 | 218 | @override 219 | int get hashCode => 0; 220 | 221 | @override 222 | bool operator ==(Object other) => 223 | identical(this, other) || other is HostPlatformType$VM; 224 | 225 | @override 226 | String toString() => 'vm'; 227 | } 228 | 229 | /// JS (browser, web, html, js) 230 | final class HostPlatformType$JS extends HostPlatformType { 231 | /// JS (browser, web, html, js) 232 | @literal 233 | const HostPlatformType$JS(); 234 | 235 | @override 236 | HostPlatformTypeResult when({ 237 | required HostPlatformTypeResult Function() vm, 238 | required HostPlatformTypeResult Function() js, 239 | }) => 240 | js(); 241 | 242 | @override 243 | bool get vm => false; 244 | 245 | @override 246 | bool get js => true; 247 | 248 | @override 249 | int get hashCode => 1; 250 | 251 | @override 252 | bool operator ==(Object other) => 253 | identical(this, other) || other is HostPlatformType$JS; 254 | 255 | @override 256 | String toString() => 'js'; 257 | } 258 | 259 | /// Operation system 260 | /// + Fuchsia 261 | /// + Linux 262 | /// + MacOS 263 | /// + Windows 264 | /// + iOS 265 | /// + Android 266 | /// + Unknown 267 | @immutable 268 | sealed class OperatingSystem { 269 | /// Build mode 270 | const OperatingSystem(); 271 | 272 | /// Android 273 | @literal 274 | const factory OperatingSystem.android() = OperatingSystem$Android; 275 | 276 | /// Fuchsia 277 | @literal 278 | const factory OperatingSystem.fuchsia() = OperatingSystem$Fuchsia; 279 | 280 | /// iOS 281 | @literal 282 | const factory OperatingSystem.iOS() = OperatingSystem$iOS; 283 | 284 | /// Linux 285 | @literal 286 | const factory OperatingSystem.linux() = OperatingSystem$Linux; 287 | 288 | /// MacOS 289 | @literal 290 | const factory OperatingSystem.macOS() = OperatingSystem$MacOS; 291 | 292 | /// Windows 293 | @literal 294 | const factory OperatingSystem.windows() = OperatingSystem$Windows; 295 | 296 | /// Unknown 297 | @literal 298 | const factory OperatingSystem.unknown() = OperatingSystem$Unknown; 299 | 300 | /// List of all operation systems 301 | static const List values = [ 302 | OperatingSystem$Android(), 303 | OperatingSystem$Fuchsia(), 304 | OperatingSystem$iOS(), 305 | OperatingSystem$Linux(), 306 | OperatingSystem$MacOS(), 307 | OperatingSystem$Windows(), 308 | OperatingSystem$Unknown(), 309 | ]; 310 | 311 | /// Operation system name 312 | abstract final String name; 313 | 314 | /// Android 315 | abstract final bool android; 316 | 317 | /// Fuchsia 318 | abstract final bool fuchsia; 319 | 320 | /// iOS 321 | abstract final bool iOS; 322 | 323 | /// Linux 324 | abstract final bool linux; 325 | 326 | /// MacOS 327 | abstract final bool macOS; 328 | 329 | /// Windows 330 | abstract final bool windows; 331 | 332 | /// Unknown 333 | abstract final bool unknown; 334 | 335 | /// Run callback on specific operation system 336 | OperatingSystemResult when({ 337 | required OperatingSystemResult Function() android, 338 | required OperatingSystemResult Function() fuchsia, 339 | required OperatingSystemResult Function() iOS, 340 | required OperatingSystemResult Function() linux, 341 | required OperatingSystemResult Function() macOS, 342 | required OperatingSystemResult Function() windows, 343 | required OperatingSystemResult Function() unknown, 344 | }); 345 | 346 | /// Run callback on specific operation system, 347 | /// if not specified run orElse 348 | OperatingSystemResult maybeWhen({ 349 | required OperatingSystemResult Function() orElse, 350 | OperatingSystemResult Function()? android, 351 | OperatingSystemResult Function()? fuchsia, 352 | OperatingSystemResult Function()? iOS, 353 | OperatingSystemResult Function()? linux, 354 | OperatingSystemResult Function()? macOS, 355 | OperatingSystemResult Function()? windows, 356 | }) => 357 | when( 358 | android: android ?? orElse, 359 | fuchsia: fuchsia ?? orElse, 360 | iOS: iOS ?? orElse, 361 | linux: linux ?? orElse, 362 | macOS: macOS ?? orElse, 363 | windows: windows ?? orElse, 364 | unknown: orElse, 365 | ); 366 | 367 | @override 368 | String toString() => name; 369 | } 370 | 371 | /// Android 372 | final class OperatingSystem$Android extends OperatingSystem { 373 | /// Android 374 | @literal 375 | const OperatingSystem$Android(); 376 | 377 | @override 378 | OperatingSystemResult when({ 379 | required OperatingSystemResult Function() android, 380 | required OperatingSystemResult Function() fuchsia, 381 | required OperatingSystemResult Function() iOS, 382 | required OperatingSystemResult Function() linux, 383 | required OperatingSystemResult Function() macOS, 384 | required OperatingSystemResult Function() windows, 385 | required OperatingSystemResult Function() unknown, 386 | }) => 387 | android(); 388 | 389 | @override 390 | String get name => 'Android'; 391 | 392 | @override 393 | bool get android => true; 394 | 395 | @override 396 | bool get fuchsia => false; 397 | 398 | @override 399 | bool get iOS => false; 400 | 401 | @override 402 | bool get linux => false; 403 | 404 | @override 405 | bool get macOS => false; 406 | 407 | @override 408 | bool get windows => false; 409 | 410 | @override 411 | bool get unknown => false; 412 | 413 | @override 414 | int get hashCode => 0; 415 | 416 | @override 417 | bool operator ==(Object other) => 418 | identical(this, other) || other is OperatingSystem$Android; 419 | } 420 | 421 | /// Fuchsia 422 | final class OperatingSystem$Fuchsia extends OperatingSystem { 423 | /// Fuchsia 424 | @literal 425 | const OperatingSystem$Fuchsia(); 426 | 427 | @override 428 | OperatingSystemResult when({ 429 | required OperatingSystemResult Function() android, 430 | required OperatingSystemResult Function() fuchsia, 431 | required OperatingSystemResult Function() iOS, 432 | required OperatingSystemResult Function() linux, 433 | required OperatingSystemResult Function() macOS, 434 | required OperatingSystemResult Function() windows, 435 | required OperatingSystemResult Function() unknown, 436 | }) => 437 | fuchsia(); 438 | 439 | @override 440 | String get name => 'Fuchsia'; 441 | 442 | @override 443 | bool get android => false; 444 | 445 | @override 446 | bool get fuchsia => true; 447 | 448 | @override 449 | bool get iOS => false; 450 | 451 | @override 452 | bool get linux => false; 453 | 454 | @override 455 | bool get macOS => false; 456 | 457 | @override 458 | bool get windows => false; 459 | 460 | @override 461 | bool get unknown => false; 462 | 463 | @override 464 | int get hashCode => 1; 465 | 466 | @override 467 | bool operator ==(Object other) => 468 | identical(this, other) || other is OperatingSystem$Fuchsia; 469 | } 470 | 471 | /// iOS 472 | final class OperatingSystem$iOS extends OperatingSystem { 473 | /// iOS 474 | @literal 475 | const OperatingSystem$iOS(); 476 | 477 | @override 478 | OperatingSystemResult when({ 479 | required OperatingSystemResult Function() android, 480 | required OperatingSystemResult Function() fuchsia, 481 | required OperatingSystemResult Function() iOS, 482 | required OperatingSystemResult Function() linux, 483 | required OperatingSystemResult Function() macOS, 484 | required OperatingSystemResult Function() windows, 485 | required OperatingSystemResult Function() unknown, 486 | }) => 487 | iOS(); 488 | 489 | @override 490 | String get name => 'iOS'; 491 | 492 | @override 493 | bool get android => false; 494 | 495 | @override 496 | bool get fuchsia => false; 497 | 498 | @override 499 | bool get iOS => true; 500 | 501 | @override 502 | bool get linux => false; 503 | 504 | @override 505 | bool get macOS => false; 506 | 507 | @override 508 | bool get windows => false; 509 | 510 | @override 511 | bool get unknown => false; 512 | 513 | @override 514 | int get hashCode => 2; 515 | 516 | @override 517 | bool operator ==(Object other) => 518 | identical(this, other) || other is OperatingSystem$iOS; 519 | } 520 | 521 | /// Linux 522 | final class OperatingSystem$Linux extends OperatingSystem { 523 | /// Linux 524 | @literal 525 | const OperatingSystem$Linux(); 526 | 527 | @override 528 | OperatingSystemResult when({ 529 | required OperatingSystemResult Function() android, 530 | required OperatingSystemResult Function() fuchsia, 531 | required OperatingSystemResult Function() iOS, 532 | required OperatingSystemResult Function() linux, 533 | required OperatingSystemResult Function() macOS, 534 | required OperatingSystemResult Function() windows, 535 | required OperatingSystemResult Function() unknown, 536 | }) => 537 | linux(); 538 | 539 | @override 540 | String get name => 'Linux'; 541 | 542 | @override 543 | bool get android => false; 544 | 545 | @override 546 | bool get fuchsia => false; 547 | 548 | @override 549 | bool get iOS => false; 550 | 551 | @override 552 | bool get linux => true; 553 | 554 | @override 555 | bool get macOS => false; 556 | 557 | @override 558 | bool get windows => false; 559 | 560 | @override 561 | bool get unknown => false; 562 | 563 | @override 564 | int get hashCode => 3; 565 | 566 | @override 567 | bool operator ==(Object other) => 568 | identical(this, other) || other is OperatingSystem$Linux; 569 | } 570 | 571 | /// macOS 572 | final class OperatingSystem$MacOS extends OperatingSystem { 573 | /// macOS 574 | @literal 575 | const OperatingSystem$MacOS(); 576 | 577 | @override 578 | OperatingSystemResult when({ 579 | required OperatingSystemResult Function() android, 580 | required OperatingSystemResult Function() fuchsia, 581 | required OperatingSystemResult Function() iOS, 582 | required OperatingSystemResult Function() linux, 583 | required OperatingSystemResult Function() macOS, 584 | required OperatingSystemResult Function() windows, 585 | required OperatingSystemResult Function() unknown, 586 | }) => 587 | macOS(); 588 | 589 | @override 590 | String get name => 'macOS'; 591 | 592 | @override 593 | bool get android => false; 594 | 595 | @override 596 | bool get fuchsia => false; 597 | 598 | @override 599 | bool get iOS => false; 600 | 601 | @override 602 | bool get linux => false; 603 | 604 | @override 605 | bool get macOS => true; 606 | 607 | @override 608 | bool get windows => false; 609 | 610 | @override 611 | bool get unknown => false; 612 | 613 | @override 614 | int get hashCode => 4; 615 | 616 | @override 617 | bool operator ==(Object other) => 618 | identical(this, other) || other is OperatingSystem$MacOS; 619 | } 620 | 621 | /// Windows 622 | final class OperatingSystem$Windows extends OperatingSystem { 623 | /// Windows 624 | @literal 625 | const OperatingSystem$Windows(); 626 | 627 | @override 628 | OperatingSystemResult when({ 629 | required OperatingSystemResult Function() android, 630 | required OperatingSystemResult Function() fuchsia, 631 | required OperatingSystemResult Function() iOS, 632 | required OperatingSystemResult Function() linux, 633 | required OperatingSystemResult Function() macOS, 634 | required OperatingSystemResult Function() windows, 635 | required OperatingSystemResult Function() unknown, 636 | }) => 637 | windows(); 638 | 639 | @override 640 | String get name => 'Windows'; 641 | 642 | @override 643 | bool get android => false; 644 | 645 | @override 646 | bool get fuchsia => false; 647 | 648 | @override 649 | bool get iOS => false; 650 | 651 | @override 652 | bool get linux => false; 653 | 654 | @override 655 | bool get macOS => false; 656 | 657 | @override 658 | bool get windows => true; 659 | 660 | @override 661 | bool get unknown => false; 662 | 663 | @override 664 | int get hashCode => 5; 665 | 666 | @override 667 | bool operator ==(Object other) => 668 | identical(this, other) || other is OperatingSystem$Windows; 669 | } 670 | 671 | /// Unknown 672 | final class OperatingSystem$Unknown extends OperatingSystem { 673 | /// Unknown 674 | @literal 675 | const OperatingSystem$Unknown(); 676 | 677 | @override 678 | OperatingSystemResult when({ 679 | required OperatingSystemResult Function() android, 680 | required OperatingSystemResult Function() fuchsia, 681 | required OperatingSystemResult Function() iOS, 682 | required OperatingSystemResult Function() linux, 683 | required OperatingSystemResult Function() macOS, 684 | required OperatingSystemResult Function() windows, 685 | required OperatingSystemResult Function() unknown, 686 | }) => 687 | unknown(); 688 | 689 | @override 690 | String get name => 'Unknown'; 691 | 692 | @override 693 | bool get android => false; 694 | 695 | @override 696 | bool get fuchsia => false; 697 | 698 | @override 699 | bool get iOS => false; 700 | 701 | @override 702 | bool get linux => false; 703 | 704 | @override 705 | bool get macOS => false; 706 | 707 | @override 708 | bool get windows => false; 709 | 710 | @override 711 | bool get unknown => true; 712 | 713 | @override 714 | int get hashCode => 6; 715 | 716 | @override 717 | bool operator ==(Object other) => 718 | identical(this, other) || other is OperatingSystem$Unknown; 719 | } 720 | -------------------------------------------------------------------------------- /lib/src/js_host_platform.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:meta/meta.dart' show immutable, internal; 4 | import 'package:web/web.dart' as web show window; 5 | 6 | import 'base_host_platform.dart'; 7 | import 'constants.dart'; 8 | import 'enums.dart'; 9 | 10 | /// Get host platform if dart.library.js_interop available 11 | @internal 12 | HostPlatform getHostPlatform() => _HostPlatform$Web._(); 13 | 14 | /// Web based host platform 15 | @immutable 16 | final class _HostPlatform$Web extends HostPlatform { 17 | _HostPlatform$Web._() 18 | : type = const HostPlatformType.js(), 19 | operatingSystem = _getOS(), 20 | version = _getVersion(), 21 | locale = _getLocale(), 22 | numberOfProcessors = _numberOfProcessors(); 23 | 24 | static bool get _isUnknownEnvironment => 25 | Zone.current[#platform_info_test.isUnknownEnvironment] as bool? ?? false; 26 | 27 | static bool get _isKnownEnvironment => !_isUnknownEnvironment; 28 | 29 | static OperatingSystem _getOS() { 30 | if (_isKnownEnvironment) { 31 | final appVersion = _getVersion().toLowerCase(); 32 | if (appVersion.contains('fuchsia')) { 33 | return const OperatingSystem.fuchsia(); 34 | } else if (appVersion.contains('mac')) { 35 | return const OperatingSystem.macOS(); 36 | } else if (appVersion.contains('win')) { 37 | return const OperatingSystem.windows(); 38 | } else if (appVersion.contains('android')) { 39 | return const OperatingSystem.android(); 40 | } else if (appVersion.contains('iphone')) { 41 | return const OperatingSystem.iOS(); 42 | } else if (appVersion.contains('ios')) { 43 | return const OperatingSystem.iOS(); 44 | } else if (appVersion.contains('linux')) { 45 | return const OperatingSystem.linux(); 46 | } 47 | } 48 | return kDefaultHostPlatform.operatingSystem; 49 | } 50 | 51 | static String _getVersion() => [ 52 | web.window.navigator.userAgent, 53 | web.window.navigator.appVersion, 54 | web.window.navigator.platform, 55 | ].firstWhere( 56 | (v) => _isKnownEnvironment && v.isNotEmpty, 57 | orElse: () => kDefaultHostPlatform.version, 58 | ); 59 | 60 | static int _numberOfProcessors() => _isKnownEnvironment 61 | ? web.window.navigator.hardwareConcurrency 62 | : kDefaultHostPlatform.numberOfProcessors; 63 | 64 | static String _getLocale() { 65 | final lang = web.window.navigator.language 66 | .split('-') 67 | .first 68 | .split('_') 69 | .first 70 | .trim() 71 | .toLowerCase(); 72 | return _isUnknownEnvironment || lang.length != 2 73 | ? kDefaultHostPlatform.locale 74 | : lang; 75 | } 76 | 77 | @override 78 | final HostPlatformType type; 79 | 80 | @override 81 | final OperatingSystem operatingSystem; 82 | 83 | @override 84 | final String version; 85 | 86 | @override 87 | final String locale; 88 | 89 | @override 90 | final int numberOfProcessors; 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/methods.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unnecessary_this 2 | 3 | import 'base_host_platform.dart'; 4 | 5 | /// Mixin with methods that extend the functionality of the platform 6 | base mixin PlatformMethods on ExtendedHostPlatform { 7 | /// Run functions that satisfy the current state of the platform. 8 | /// You can use nested methods to compose more complex queries. 9 | /// Can return null, if [orElse] not set and any callback was not called. 10 | /// 11 | /// ### Operating System 12 | /// [fuchsia] - whether the operating system is a version of Fuchsia 13 | /// [windows] - whether the operating system is a version of Windows 14 | /// [android] - whether the operating system is a version of Android 15 | /// [iOS] - whether the operating system is a version of iOS 16 | /// [macOS] - whether the operating system is a version of MacOS 17 | /// [linux] - whether the operating system is a version of Linux 18 | /// [unknown] - operating system unknown 19 | /// 20 | /// ### Design 21 | /// [material] - is material (Android, Fuchsia) 22 | /// [cupertino] - is cupertino (macOS, iOS) 23 | /// 24 | /// ### Mobile or desktop 25 | /// [mobile] - is mobile device (Android, iOS) 26 | /// [desktop] - is desktop device (Windows, MacOS, Fuchsia) 27 | /// 28 | /// ### IO or Web 29 | /// [js] - is web-based applications 30 | /// [vm] - is I/O supporting for non-web applications 31 | /// 32 | /// ### Build mode 33 | /// [release] - release build mode 34 | /// [profile] - profile build mode 35 | /// [debug] - debug build mode 36 | /// 37 | /// [orElse] - any callback was not called 38 | /// 39 | /// ### Sequence of checks 40 | /// 1. Operating System 41 | /// 2. Design 42 | /// 3. Mobile/Desktop 43 | /// 4. IO/Web 44 | /// 5. Build mode 45 | /// 6. Call [orElse] if any callback was not called 46 | /// 47 | /// Example: 48 | /// ```dart 49 | /// final result = platform.when( 50 | /// io: () => platform.when( 51 | /// fuchsia: () => ..., 52 | /// windows: () => ..., 53 | /// android: () => ..., 54 | /// iOS: () => ..., 55 | /// macOS: () => ..., 56 | /// linux: () => ..., 57 | /// unknown: () => ..., 58 | /// orElse: () => ..., 59 | /// ), 60 | /// web: () => platform.when( 61 | /// material: () => ..., 62 | /// cupertino: () => ..., 63 | /// orElse: () => ..., 64 | /// ), 65 | /// orElse: () => ..., 66 | /// ); 67 | /// ``` 68 | /// 69 | PlatformResult? when({ 70 | PlatformResult Function()? fuchsia, 71 | PlatformResult Function()? windows, 72 | PlatformResult Function()? android, 73 | PlatformResult Function()? iOS, 74 | PlatformResult Function()? macOS, 75 | PlatformResult Function()? linux, 76 | PlatformResult Function()? unknown, 77 | PlatformResult Function()? material, 78 | PlatformResult Function()? cupertino, 79 | PlatformResult Function()? mobile, 80 | PlatformResult Function()? desktop, 81 | PlatformResult Function()? vm, 82 | PlatformResult Function()? js, 83 | PlatformResult Function()? release, 84 | PlatformResult Function()? profile, 85 | PlatformResult Function()? debug, 86 | PlatformResult Function()? orElse, 87 | }) { 88 | { 89 | // Operating System 90 | if (fuchsia != null && this.fuchsia) { 91 | return fuchsia(); 92 | } else if (windows != null && this.windows) { 93 | return windows(); 94 | } else if (android != null && this.android) { 95 | return android(); 96 | } else if (iOS != null && this.iOS) { 97 | return iOS(); 98 | } else if (macOS != null && this.macOS) { 99 | return macOS(); 100 | } else if (linux != null && this.linux) { 101 | return linux(); 102 | } else if (unknown != null && this.unknown) { 103 | return unknown(); 104 | } 105 | } 106 | 107 | { 108 | // Design 109 | if (material != null && this.material) { 110 | return material(); 111 | } else if (cupertino != null && this.cupertino) { 112 | return cupertino(); 113 | } 114 | } 115 | 116 | { 117 | // Mobile/Desktop 118 | if (mobile != null && this.mobile) { 119 | return mobile(); 120 | } else if (desktop != null && this.desktop) { 121 | return desktop(); 122 | } 123 | } 124 | 125 | { 126 | // IO/Web 127 | if (vm != null && this.vm) { 128 | return vm(); 129 | } else if (js != null && this.js) { 130 | return js(); 131 | } 132 | } 133 | 134 | { 135 | // Build mode 136 | if (debug != null && this.buildMode.debug) { 137 | return debug(); 138 | } else if (profile != null && this.buildMode.profile) { 139 | return profile(); 140 | } else if (release != null && this.buildMode.release) { 141 | return release(); 142 | } 143 | } 144 | 145 | // Any callback was not called 146 | return orElse != null ? orElse() : null; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/src/platform.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes 2 | 3 | import 'package:meta/meta.dart' show immutable, visibleForTesting; 4 | 5 | import 'base_host_platform.dart'; 6 | import 'constants.dart'; 7 | import 'default_host_platform.dart'; 8 | import 'enums.dart'; 9 | import 'methods.dart'; 10 | import 'stub_host_platform.dart' 11 | if (dart.library.js_interop) 'js_host_platform.dart' 12 | if (dart.library.io) 'vm_host_platform.dart'; 13 | 14 | /// [Platform] info 15 | /// Works on the web, mobile phones, desktops and console. 16 | /// Provides platform information such as: 17 | /// + Build mode 18 | /// * release (release build mode) 19 | /// * profile (profile build mode) 20 | /// * debug (debug build mode) 21 | /// 22 | /// + Host platform type 23 | /// * io (desktops, mobile, console) 24 | /// * web (browser) 25 | /// 26 | /// + Operation system 27 | /// * Fuchsia 28 | /// * Linux 29 | /// * MacOS 30 | /// * Windows 31 | /// * iOS 32 | /// * Android 33 | /// * Unknown 34 | /// 35 | /// + Version 36 | /// 37 | /// + Locale string 38 | /// 39 | /// + The number of individual execution units of the machine. 40 | /// 41 | /// + Operating system is known type 42 | /// 43 | /// + Is mobile device (Android, iOS) 44 | /// 45 | /// + Is desktop device (Windows, MacOS, Fuchsia) 46 | /// 47 | /// + Is material (Android, Fuchsia) 48 | /// 49 | /// + Is cupertino (MacOS, iOS) 50 | /// 51 | @immutable 52 | final class Platform extends ExtendedHostPlatform with PlatformMethods { 53 | /// Access to the Singleton instance of Platform 54 | static Platform get instance => _this; 55 | 56 | /// Short form to access the instance of Platform 57 | static Platform get I => _this; 58 | 59 | /// Singleton info about platform 60 | static final Platform _this = Platform._internalFactoryFromEnvironment(); 61 | 62 | /// Get current build mode 63 | static BuildMode _$getCurrentBuildMode() => () { 64 | if (const bool.fromEnvironment('dart.vm.product')) { 65 | return const BuildMode.release(); 66 | } 67 | var result = const BuildMode.profile(); 68 | assert(() { 69 | result = const BuildMode.debug(); 70 | return true; 71 | }(), ''); 72 | return result; 73 | }(); 74 | 75 | /// Get host platform 76 | static HostPlatform _$getHostPlatform() { 77 | try { 78 | return getHostPlatform(); 79 | } on Object { 80 | return const DefaultHostPlatform(); 81 | } 82 | } 83 | 84 | /// Internal factory from environment 85 | factory Platform._internalFactoryFromEnvironment() => Platform._internal( 86 | buildMode: _$getCurrentBuildMode(), 87 | hostPlatform: _$getHostPlatform(), 88 | ); 89 | 90 | /// Internal constructor 91 | Platform._internal({ 92 | required this.buildMode, 93 | required HostPlatform hostPlatform, 94 | }) : _hostPlatform = hostPlatform, 95 | mobile = kListOSForMobile.contains(hostPlatform.operatingSystem), 96 | desktop = kListOSForDesktop.contains(hostPlatform.operatingSystem), 97 | material = 98 | kListOSWithMaterialDesign.contains(hostPlatform.operatingSystem), 99 | cupertino = 100 | kListOSWithCupertinoDesign.contains(hostPlatform.operatingSystem); 101 | 102 | @override 103 | HostPlatformType get type => _hostPlatform.type; 104 | 105 | @override 106 | OperatingSystem get operatingSystem => _hostPlatform.operatingSystem; 107 | 108 | @override 109 | String get version => _hostPlatform.version; 110 | 111 | @override 112 | String get locale => _hostPlatform.locale; 113 | 114 | @override 115 | int get numberOfProcessors => _hostPlatform.numberOfProcessors; 116 | 117 | @override 118 | bool get js => _hostPlatform.type.js; 119 | 120 | @override 121 | bool get vm => _hostPlatform.type.vm; 122 | 123 | @override 124 | final bool mobile; 125 | 126 | @override 127 | final bool desktop; 128 | 129 | @override 130 | final bool material; 131 | 132 | @override 133 | final bool cupertino; 134 | 135 | @override 136 | bool get android => operatingSystem.android; 137 | 138 | @override 139 | bool get fuchsia => operatingSystem.fuchsia; 140 | 141 | @override 142 | bool get iOS => operatingSystem.iOS; 143 | 144 | @override 145 | bool get linux => operatingSystem.linux; 146 | 147 | @override 148 | bool get macOS => operatingSystem.macOS; 149 | 150 | @override 151 | bool get windows => operatingSystem.windows; 152 | 153 | @override 154 | bool get unknown => operatingSystem.unknown; 155 | 156 | @override 157 | final BuildMode buildMode; 158 | 159 | /// Host platform contain info about host device 160 | final HostPlatform _hostPlatform; 161 | 162 | @override 163 | int get hashCode => 0; 164 | 165 | @override 166 | bool operator ==(Object other) => other is Platform; 167 | 168 | @override 169 | String toString() => version; 170 | } 171 | 172 | /// Fake class for test needs 173 | @immutable 174 | @visibleForTesting 175 | final class FakePlatform extends Platform { 176 | /// Fake constructor for test needs 177 | FakePlatform({ 178 | BuildMode? buildMode, 179 | HostPlatformType? type, 180 | OperatingSystem? operatingSystem, 181 | String? version, 182 | String? locale, 183 | int? numberOfProcessors, 184 | }) : super._internal( 185 | buildMode: buildMode ?? const BuildMode.debug(), 186 | hostPlatform: _FakeHostPlatform( 187 | type: type ?? const DefaultHostPlatform().type, 188 | operatingSystem: 189 | operatingSystem ?? const DefaultHostPlatform().operatingSystem, 190 | version: version ?? const DefaultHostPlatform().version, 191 | locale: locale ?? const DefaultHostPlatform().locale, 192 | numberOfProcessors: numberOfProcessors ?? 193 | const DefaultHostPlatform().numberOfProcessors, 194 | ), 195 | ); 196 | } 197 | 198 | /// Fake class for test needs 199 | @immutable 200 | final class _FakeHostPlatform extends HostPlatform { 201 | /// Fake constructor for test needs 202 | const _FakeHostPlatform({ 203 | required this.locale, 204 | required this.numberOfProcessors, 205 | required this.operatingSystem, 206 | required this.type, 207 | required this.version, 208 | }); 209 | 210 | @override 211 | final String locale; 212 | 213 | @override 214 | final int numberOfProcessors; 215 | 216 | @override 217 | final OperatingSystem operatingSystem; 218 | 219 | @override 220 | final HostPlatformType type; 221 | 222 | @override 223 | final String version; 224 | } 225 | -------------------------------------------------------------------------------- /lib/src/stub_host_platform.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | import 'base_host_platform.dart'; 4 | import 'default_host_platform.dart'; 5 | 6 | /// Get host platform if dart.library.html and dart.library.io available 7 | /// Return unknown host platform with default values 8 | @internal 9 | HostPlatform getHostPlatform() => const DefaultHostPlatform(); 10 | -------------------------------------------------------------------------------- /lib/src/vm_host_platform.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io' as io; 3 | 4 | import 'base_host_platform.dart'; 5 | import 'constants.dart'; 6 | import 'enums.dart'; 7 | 8 | /// Get host platform if dart.library.io available 9 | HostPlatform getHostPlatform() => _HostPlatform$IO._(); 10 | 11 | /// i/o based host platform 12 | final class _HostPlatform$IO extends HostPlatform { 13 | _HostPlatform$IO._() 14 | : operatingSystem = _getOS(), 15 | version = _getVersion(), 16 | locale = _getLocale(), 17 | numberOfProcessors = _numberOfProcessors(); 18 | 19 | static bool get _isUnknownEnvironment => 20 | Zone.current[#platform_info_test.isUnknownEnvironment] as bool? ?? false; 21 | 22 | static bool get _isKnownEnvironment => !_isUnknownEnvironment; 23 | 24 | static OperatingSystem _getOS() { 25 | if (_isKnownEnvironment) { 26 | if (io.Platform.isFuchsia) { 27 | return const OperatingSystem.fuchsia(); 28 | } else if (io.Platform.isWindows) { 29 | return const OperatingSystem.windows(); 30 | } else if (io.Platform.isAndroid) { 31 | return const OperatingSystem.android(); 32 | } else if (io.Platform.isMacOS) { 33 | return const OperatingSystem.macOS(); 34 | } else if (io.Platform.isIOS) { 35 | return const OperatingSystem.iOS(); 36 | } else if (io.Platform.isLinux) { 37 | return const OperatingSystem.linux(); 38 | } 39 | } 40 | return kDefaultHostPlatform.operatingSystem; 41 | } 42 | 43 | static String _getVersion() => _isKnownEnvironment 44 | ? io.Platform.operatingSystemVersion 45 | : kDefaultHostPlatform.version; 46 | 47 | static int _numberOfProcessors() => _isKnownEnvironment 48 | ? io.Platform.numberOfProcessors 49 | : kDefaultHostPlatform.numberOfProcessors; 50 | 51 | static String _getLocale() { 52 | final lang = io.Platform.localeName 53 | .split('-') 54 | .first 55 | .split('_') 56 | .first 57 | .trim() 58 | .toLowerCase(); 59 | if (_isUnknownEnvironment || lang.length != 2) { 60 | return kDefaultHostPlatform.locale; 61 | } 62 | return lang; 63 | } 64 | 65 | @override 66 | final HostPlatformType type = const HostPlatformType.vm(); 67 | 68 | @override 69 | final OperatingSystem operatingSystem; 70 | 71 | @override 72 | final String version; 73 | 74 | @override 75 | final String locale; 76 | 77 | @override 78 | final int numberOfProcessors; 79 | } 80 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_info 2 | description: > 3 | Contains info about current platform 4 | such as Build mode and Operating system. 5 | version: 5.0.0 6 | repository: https://github.com/PlugFox/platform_info/tree/master 7 | issue_tracker: https://github.com/PlugFox/platform_info/issues 8 | homepage: https://github.com/PlugFox/platform_info 9 | #author: Plague Fox 10 | #documentation: https://pub.dev/documentation/platform_info/latest 11 | 12 | funding: 13 | - https://www.buymeacoffee.com/plugfox 14 | - https://www.patreon.com/plugfox 15 | - https://boosty.to/plugfox 16 | 17 | topics: 18 | - platform 19 | - info 20 | - cross-platform 21 | - device 22 | - information 23 | 24 | platforms: 25 | android: 26 | ios: 27 | linux: 28 | macos: 29 | web: 30 | windows: 31 | 32 | screenshots: 33 | - description: 'Example of using the library to get the current platform info' 34 | path: example.png 35 | 36 | environment: 37 | sdk: ">=3.4.0 <4.0.0" 38 | 39 | dependencies: 40 | meta: ^1.9.1 41 | web: ^1.0.0 42 | 43 | dev_dependencies: 44 | lints: ">=4.0.0 <5.0.0" 45 | test: ^1.24.2 -------------------------------------------------------------------------------- /test/test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:platform_info/platform_info.dart'; 4 | import 'package:platform_info/src/default_host_platform.dart'; 5 | import 'package:platform_info/src/stub_host_platform.dart' as stub; 6 | import 'package:test/test.dart'; 7 | 8 | // ignore_for_file: unnecessary_statements, avoid_print, cascade_invocations 9 | // ignore_for_file: unnecessary_lambdas, unnecessary_type_check 10 | 11 | void main() { 12 | group('Platform', () { 13 | test('shouldRun', () { 14 | expect(Platform.I, platform); 15 | expect(() => Platform.I, returnsNormally); 16 | }); 17 | 18 | test('shouldCreate', () { 19 | final platform = Platform.I; 20 | expect(platform, isA()); 21 | }); 22 | 23 | test('types', () { 24 | expect(platform, isA()); 25 | expect(platform.buildMode, isA()); 26 | expect(platform.js, isA()); 27 | expect(platform.vm, isA()); 28 | expect(platform.desktop, isA()); 29 | expect(platform.mobile, isA()); 30 | expect(platform.cupertino, isA()); 31 | expect(platform.material, isA()); 32 | expect(platform.unknown, isA()); 33 | expect(platform.locale, isA()); 34 | expect(platform.numberOfProcessors, isA()); 35 | expect(platform.operatingSystem, isA()); 36 | expect(platform.type, isA()); 37 | expect(platform.version, isA()); 38 | expect(platform.android, isA()); 39 | expect(platform.windows, isA()); 40 | expect(platform.fuchsia, isA()); 41 | expect(platform.iOS, isA()); 42 | expect(platform.linux, isA()); 43 | expect(platform.macOS, isA()); 44 | }); 45 | 46 | test('identical', () { 47 | final platform1 = Platform.I; 48 | final platform2 = Platform.instance; 49 | final platform3 = platform; 50 | expect(platform1 == platform2, true); 51 | expect(platform2 == platform3, true); 52 | expect(identical(platform1, platform2), true); 53 | expect(identical(platform2, platform3), true); 54 | expect(platform1, platform2); 55 | expect(platform2, platform3); 56 | }); 57 | 58 | test('hashcode', () { 59 | final platform1 = Platform.I; 60 | final platform2 = platform; 61 | expect(platform1.hashCode, 0); 62 | expect(platform1.hashCode, platform2.hashCode); 63 | }); 64 | 65 | test('toString', () { 66 | expect(Platform.I.toString(), Platform.I.version); 67 | }); 68 | }); 69 | 70 | group('Stub platform', () { 71 | test('Default values', () { 72 | final stubPlatform = stub.getHostPlatform(); 73 | const type = 74 | identical(0, 0.0) ? HostPlatformType.js() : HostPlatformType.vm(); 75 | expect(() => const DefaultHostPlatform(), returnsNormally); 76 | expect(stubPlatform, isA()); 77 | expect( 78 | stubPlatform.operatingSystem, same(const OperatingSystem.unknown())); 79 | expect(stubPlatform.numberOfProcessors, 0); 80 | expect(stubPlatform.locale, 'en'); 81 | expect(stubPlatform.version, 'unknown'); 82 | expect(stubPlatform.type, type); 83 | }); 84 | }); 85 | 86 | group('platform test', () { 87 | test('unknown environment', () { 88 | runZoned( 89 | () { 90 | const platform = DefaultHostPlatform(); 91 | expect( 92 | platform.operatingSystem, same(const OperatingSystem.unknown())); 93 | expect(platform.numberOfProcessors, 0); 94 | expect(platform.locale, 'en'); 95 | expect(platform.version, 'unknown'); 96 | expect( 97 | platform.type, 98 | anyOf( 99 | const HostPlatformType.vm(), 100 | const HostPlatformType.js(), 101 | )); 102 | }, 103 | zoneValues: {#platform_info_test.isUnknownEnvironment: true}, 104 | ); 105 | }); 106 | }, onPlatform: { 107 | 'android': const Timeout.factor(2), 108 | 'ios': const Timeout.factor(2), 109 | /* 'browser': const Skip('Not supported on Browser'), */ 110 | }); 111 | 112 | group('PlatformMethods', () { 113 | bool returnTrue() => true; 114 | bool returnFalse() => false; 115 | 116 | test('Chaining', () { 117 | expect( 118 | platform.when( 119 | vm: () => platform.when( 120 | material: returnTrue, 121 | cupertino: returnTrue, 122 | orElse: returnTrue, 123 | ), 124 | js: returnTrue, 125 | orElse: returnFalse, 126 | ), 127 | isTrue); 128 | }); 129 | 130 | test('Operating System', () { 131 | expect( 132 | FakePlatform( 133 | operatingSystem: const OperatingSystem.fuchsia(), 134 | ).when( 135 | fuchsia: returnTrue, 136 | orElse: returnFalse, 137 | ), 138 | isTrue); 139 | 140 | expect( 141 | FakePlatform( 142 | operatingSystem: const OperatingSystem.windows(), 143 | ).when( 144 | windows: returnTrue, 145 | orElse: returnFalse, 146 | ), 147 | isTrue); 148 | 149 | expect( 150 | FakePlatform( 151 | operatingSystem: const OperatingSystem.android(), 152 | ).when( 153 | android: returnTrue, 154 | orElse: returnFalse, 155 | ), 156 | isTrue); 157 | 158 | expect( 159 | FakePlatform( 160 | operatingSystem: const OperatingSystem.iOS(), 161 | ).when( 162 | iOS: returnTrue, 163 | orElse: returnFalse, 164 | ), 165 | isTrue); 166 | 167 | expect( 168 | FakePlatform( 169 | operatingSystem: const OperatingSystem.macOS(), 170 | ).when( 171 | macOS: returnTrue, 172 | orElse: returnFalse, 173 | ), 174 | isTrue); 175 | 176 | expect( 177 | FakePlatform( 178 | operatingSystem: const OperatingSystem.linux(), 179 | ).when( 180 | linux: returnTrue, 181 | orElse: returnFalse, 182 | ), 183 | isTrue); 184 | 185 | expect( 186 | FakePlatform( 187 | operatingSystem: const OperatingSystem.unknown(), 188 | ).when( 189 | unknown: returnTrue, 190 | orElse: returnFalse, 191 | ), 192 | isTrue); 193 | }); 194 | 195 | test('Design', () { 196 | expect( 197 | FakePlatform( 198 | operatingSystem: const OperatingSystem.android(), 199 | ).when( 200 | material: returnTrue, 201 | orElse: returnFalse, 202 | ), 203 | isTrue); 204 | 205 | expect( 206 | FakePlatform( 207 | operatingSystem: const OperatingSystem.iOS(), 208 | ).when( 209 | cupertino: returnTrue, 210 | orElse: returnFalse, 211 | ), 212 | isTrue); 213 | }); 214 | 215 | test('Mobile/Desktop', () { 216 | expect( 217 | FakePlatform( 218 | operatingSystem: const OperatingSystem.android(), 219 | ).when( 220 | mobile: returnTrue, 221 | orElse: returnFalse, 222 | ), 223 | isTrue); 224 | 225 | expect( 226 | FakePlatform( 227 | operatingSystem: const OperatingSystem.windows(), 228 | ).when( 229 | desktop: returnTrue, 230 | orElse: returnFalse, 231 | ), 232 | isTrue); 233 | }); 234 | 235 | test('IO or Web', () { 236 | expect( 237 | FakePlatform( 238 | type: const HostPlatformType.vm(), 239 | ).when( 240 | vm: returnTrue, 241 | orElse: returnFalse, 242 | ), 243 | isTrue); 244 | 245 | expect( 246 | FakePlatform( 247 | type: const HostPlatformType.js(), 248 | ).when( 249 | js: returnTrue, 250 | orElse: returnFalse, 251 | ), 252 | isTrue); 253 | }); 254 | 255 | test('Build mode', () { 256 | expect( 257 | FakePlatform( 258 | buildMode: const BuildMode.debug(), 259 | ).when( 260 | debug: returnTrue, 261 | orElse: returnFalse, 262 | ), 263 | isTrue); 264 | 265 | expect( 266 | FakePlatform( 267 | buildMode: const BuildMode.profile(), 268 | ).when( 269 | profile: returnTrue, 270 | orElse: returnFalse, 271 | ), 272 | isTrue); 273 | 274 | expect( 275 | FakePlatform( 276 | buildMode: const BuildMode.release(), 277 | ).when( 278 | release: returnTrue, 279 | orElse: returnFalse, 280 | ), 281 | isTrue); 282 | }); 283 | 284 | test('orElse', () { 285 | expect( 286 | FakePlatform().when( 287 | orElse: returnTrue, 288 | ), 289 | isTrue); 290 | 291 | expect( 292 | FakePlatform().when( 293 | orElse: returnFalse, 294 | ), 295 | isFalse); 296 | 297 | expect( 298 | FakePlatform().when(), 299 | isNull, 300 | ); 301 | }); 302 | }); 303 | 304 | group('Enum extensions', () { 305 | test('BuildMode', () { 306 | expect(const BuildMode.release().release, isTrue); 307 | expect(const BuildMode.profile().profile, isTrue); 308 | expect(const BuildMode.debug().debug, isTrue); 309 | expect( 310 | const BuildMode.release().maybeWhen( 311 | orElse: () => false, 312 | debug: () => false, 313 | profile: () => false, 314 | release: () => true, 315 | ), 316 | isTrue, 317 | ); 318 | expect( 319 | const BuildMode.profile().maybeWhen( 320 | orElse: () => false, 321 | debug: () => false, 322 | profile: () => true, 323 | release: () => false, 324 | ), 325 | isTrue, 326 | ); 327 | expect( 328 | const BuildMode.debug().maybeWhen( 329 | orElse: () => false, 330 | debug: () => true, 331 | profile: () => false, 332 | release: () => false, 333 | ), 334 | isTrue, 335 | ); 336 | expect( 337 | const BuildMode.debug().maybeWhen( 338 | orElse: () => true, 339 | release: () => false, 340 | profile: () => false, 341 | ), 342 | isTrue, 343 | ); 344 | }); 345 | 346 | test('HostPlatformType', () { 347 | expect(const HostPlatformType.vm().vm, isTrue); 348 | expect(const HostPlatformType.js().js, isTrue); 349 | expect( 350 | const HostPlatformType.vm().when( 351 | vm: () => true, 352 | js: () => false, 353 | ), 354 | isTrue, 355 | ); 356 | expect( 357 | const HostPlatformType.js().when( 358 | vm: () => false, 359 | js: () => true, 360 | ), 361 | isTrue, 362 | ); 363 | }); 364 | 365 | test('OperatingSystem', () { 366 | expect(const OperatingSystem.fuchsia().fuchsia, isTrue); 367 | expect(const OperatingSystem.unknown().unknown, isTrue); 368 | expect(const OperatingSystem.android().android, isTrue); 369 | expect(const OperatingSystem.iOS().iOS, isTrue); 370 | expect(const OperatingSystem.linux().linux, isTrue); 371 | expect(const OperatingSystem.macOS().macOS, isTrue); 372 | expect(const OperatingSystem.windows().windows, isTrue); 373 | 374 | expect( 375 | const OperatingSystem.fuchsia().maybeWhen( 376 | fuchsia: () => true, 377 | orElse: () => false, 378 | ), 379 | isTrue, 380 | ); 381 | 382 | expect( 383 | const OperatingSystem.windows().maybeWhen( 384 | windows: () => true, 385 | orElse: () => false, 386 | ), 387 | isTrue, 388 | ); 389 | 390 | expect( 391 | const OperatingSystem.macOS().maybeWhen( 392 | macOS: () => true, 393 | orElse: () => false, 394 | ), 395 | isTrue, 396 | ); 397 | 398 | expect( 399 | const OperatingSystem.linux().maybeWhen( 400 | linux: () => true, 401 | orElse: () => false, 402 | ), 403 | isTrue, 404 | ); 405 | 406 | expect( 407 | const OperatingSystem.iOS().maybeWhen( 408 | iOS: () => true, 409 | orElse: () => false, 410 | ), 411 | isTrue, 412 | ); 413 | 414 | expect( 415 | const OperatingSystem.android().maybeWhen( 416 | android: () => true, 417 | orElse: () => false, 418 | ), 419 | isTrue, 420 | ); 421 | 422 | expect( 423 | const OperatingSystem.unknown().maybeWhen( 424 | fuchsia: () => false, 425 | orElse: () => true, 426 | ), 427 | isTrue, 428 | ); 429 | }); 430 | }); 431 | } 432 | --------------------------------------------------------------------------------