diff --git a/CHANGELOG.md b/CHANGELOG.md index 038ee0f..3371d2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 2.0.4 + * Fixes Platform.operatingSystemVersion ([issue #9](https://github.com/dint-dev/universal_io/issues/9)). + # 2.0.3 * Fixes various issues. diff --git a/README.md b/README.md index 2ae41c4..25f2e59 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ [![Github Actions CI](https://github.com/dint-dev/universal_io/workflows/Dart%20CI/badge.svg)](https://github.com/dint-dev/universal_io/actions?query=workflow%3A%22Dart+CI%22) # Overview -A cross-platform _dart:io_ that works in all platforms (browsers, mobile, desktop, and server-side, -and Node.JS). +A cross-platform _dart:io_ that works in all platforms (browsers, mobile, desktop, and server-side). The API is exactly the same API as _dart:io_. You can simply replace _dart:io_ imports with _package:universal_io/io.dart_. Normal _dart:io_ will continue to be used when your application runs @@ -23,13 +22,13 @@ which was obtained under the BSD-style license of Dart SDK. See LICENSE file for # Getting started -### pubspec.yaml +## 1.Add dependency ```yaml dependencies: - universal_io: ^2.0.3 + universal_io: ^2.0.4 ``` -### main.dart +## 2.Use APIs ```dart import 'package:universal_io/io.dart'; @@ -42,10 +41,17 @@ Future main() async { } ``` -# Browser driver +# Behavior in browsers +## Platform +The following [Platform](https://api.dart.dev/stable/2.12.2/dart-io/Platform-class.html) APIs work +in browsers: + * Platform.locale + * Platform.operatingSystem + * Platform.operatingSystemVersion + ## HTTP client HTTP client is implemented with [XMLHttpRequest (XHR)](https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest) -(in _dart:html_, the class is [HttpRequest](https://api.dart.dev/stable/2.7.1/dart-html/HttpRequest-class.html)). +(in _dart:html_, the class is [HttpRequest](https://api.dart.dev/stable/2.12.2/dart-html/HttpRequest-class.html)). XHR causes the following differences with _dart:io_: * HTTP connection is created only after `request.close()` has been called. diff --git a/lib/src/internals_for_browser_or_node_impl_browser.dart b/lib/src/internals_for_browser_or_node_impl_browser.dart index 966d392..3baf1e6 100644 --- a/lib/src/internals_for_browser_or_node_impl_browser.dart +++ b/lib/src/internals_for_browser_or_node_impl_browser.dart @@ -25,29 +25,92 @@ import 'io_impl_js.dart'; String get locale { final languages = html.window.navigator.languages; - if (languages!=null && languages.isNotEmpty) { + if (languages != null && languages.isNotEmpty) { return languages.first; } return 'en-US'; } -String get platform { - final s = html.window.navigator.platform?.toLowerCase() ?? html.window.navigator.userAgent; +String get operatingSystem { + final s = html.window.navigator.userAgent.toLowerCase(); if (s.contains('iphone') || s.contains('ipad') || - s.contains('ipod')) { + s.contains('ipod') || + s.contains('watch os')) { return 'ios'; } - if (s.contains('mac')) { + if (s.contains('mac os')) { return 'macos'; } + if (s.contains('fuchsia')) { + return 'fuchsia'; + } if (s.contains('android')) { return 'android'; } - if (s.contains('linux')) { + if (s.contains('linux') || s.contains('cros') || s.contains('chromebook')) { return 'linux'; } - return 'windows'; + if (s.contains('windows')) { + return 'windows'; + } + return ''; +} + +String get operatingSystemVersion { + final userAgent = html.window.navigator.userAgent; + + // Android? + { + final regExp = RegExp('Android ([a-zA-Z0-9.-_]+)'); + final match = regExp.firstMatch(userAgent); + if (match != null) { + final version = match.group(1) ?? ''; + return version; + } + } + + // iPhone OS? + { + final regExp = RegExp('iPhone OS ([a-zA-Z0-9.-_]+) ([a-zA-Z0-9.-_]+)'); + final match = regExp.firstMatch(userAgent); + if (match != null) { + final version = (match.group(2) ?? '').replaceAll('_', '.'); + return version; + } + } + + // Mac OS X? + { + final regExp = RegExp('Mac OS X ([a-zA-Z0-9.-_]+)'); + final match = regExp.firstMatch(userAgent); + if (match != null) { + final version = (match.group(1) ?? '').replaceAll('_', '.'); + return version; + } + } + + // Chrome OS? + { + final regExp = RegExp('CrOS ([a-zA-Z0-9.-_]+) ([a-zA-Z0-9.-_]+)'); + final match = regExp.firstMatch(userAgent); + if (match != null) { + final version = match.group(2) ?? ''; + return version; + } + } + + // Windows NT? + { + final regExp = RegExp('Windows NT ([a-zA-Z0-9.-_]+)'); + final match = regExp.firstMatch(userAgent); + if (match != null) { + final version = (match.group(1) ?? ''); + return version; + } + } + + return ''; } HttpClient newHttpClient() { diff --git a/lib/src/internals_for_browser_or_node_impl_node.dart b/lib/src/internals_for_browser_or_node_impl_node.dart index 73aaa31..400df91 100644 --- a/lib/src/internals_for_browser_or_node_impl_node.dart +++ b/lib/src/internals_for_browser_or_node_impl_node.dart @@ -28,6 +28,10 @@ String get locale { return 'en-US'; } -String get platform { +String get operatingSystem { return 'linux'; } + +String get operatingSystemVersion { + return ''; +} diff --git a/lib/src/io/platform.dart b/lib/src/io/platform.dart index a30ca7f..6806043 100644 --- a/lib/src/io/platform.dart +++ b/lib/src/io/platform.dart @@ -165,10 +165,10 @@ class Platform { static int get numberOfProcessors => 1; /// A string representing the operating system or platform. - static String get operatingSystem => browser_or_node.platform; + static String get operatingSystem => browser_or_node.operatingSystem; /// A string representing the version of the operating system or platform. - static String get operatingSystemVersion => ''; + static String get operatingSystemVersion => browser_or_node.operatingSystemVersion; /// The `--packages` flag passed to the executable used to run the script /// in this isolate. diff --git a/pubspec.yaml b/pubspec.yaml index d2ebca0..c7e6915 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: universal_io -version: 2.0.3 +version: 2.0.4 description: Cross-platform 'dart:io' that works in all platforms (browsers, Flutter, and VM). homepage: https://github.com/dart-io-packages/universal_io diff --git a/test/helpers_impl_browser.dart b/test/helpers_impl_browser.dart index f330072..b724fa6 100644 --- a/test/helpers_impl_browser.dart +++ b/test/helpers_impl_browser.dart @@ -25,7 +25,8 @@ void testPlatformInBrowser() { }); } - if ((window.navigator.platform ?? '').contains('Mac')) { + final userAgent = (window.navigator.userAgent ?? '').toLowerCase(); + if (userAgent.contains('mac os x')) { test('Platform.isMacOS == true', () { expect(Platform.isMacOS, true); }); @@ -35,9 +36,10 @@ void testPlatformInBrowser() { test('Platform.isLinux == false', () { expect(Platform.isLinux, false); }); - } - - if ((window.navigator.platform ?? '').contains('Win')) { + test('Platform.operatingSystemVersion', () { + expect(Platform.operatingSystemVersion, isNotEmpty); + }); + } else if (userAgent.contains('windows')) { test('Platform.isMacOS == false', () { expect(Platform.isMacOS, false); }); @@ -47,17 +49,21 @@ void testPlatformInBrowser() { test('Platform.isLinux == false', () { expect(Platform.isLinux, false); }); - - if ((window.navigator.platform ?? '').contains('Linux')) { - test('Platform.isMacOS == true', () { - expect(Platform.isMacOS, false); - }); - test('Platform.isWindows == false', () { - expect(Platform.isWindows, false); - }); - test('Platform.isLinux == true', () { - expect(Platform.isLinux, true); - }); - } + test('Platform.operatingSystemVersion', () { + expect(Platform.operatingSystemVersion, isNotEmpty); + }); + } else if (userAgent.contains('linux')) { + test('Platform.isMacOS == false', () { + expect(Platform.isMacOS, false); + }); + test('Platform.isWindows == false', () { + expect(Platform.isWindows, false); + }); + test('Platform.isLinux == true', () { + expect(Platform.isLinux, true); + }); + test('Platform.operatingSystemVersion', () { + expect(Platform.operatingSystemVersion, isNotEmpty); + }); } }