Jonatas

added GetConnect

Showing 70 changed files with 2738 additions and 39 deletions
  1 +gradle-wrapper.jar
  2 +/.gradle
  3 +/captures/
  4 +/gradlew
  5 +/gradlew.bat
  6 +/local.properties
  7 +GeneratedPluginRegistrant.java
  8 +
  9 +# Remember to never publicly share your keystore.
  10 +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
  11 +key.properties
  1 +def localProperties = new Properties()
  2 +def localPropertiesFile = rootProject.file('local.properties')
  3 +if (localPropertiesFile.exists()) {
  4 + localPropertiesFile.withReader('UTF-8') { reader ->
  5 + localProperties.load(reader)
  6 + }
  7 +}
  8 +
  9 +def flutterRoot = localProperties.getProperty('flutter.sdk')
  10 +if (flutterRoot == null) {
  11 + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
  12 +}
  13 +
  14 +def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
  15 +if (flutterVersionCode == null) {
  16 + flutterVersionCode = '1'
  17 +}
  18 +
  19 +def flutterVersionName = localProperties.getProperty('flutter.versionName')
  20 +if (flutterVersionName == null) {
  21 + flutterVersionName = '1.0'
  22 +}
  23 +
  24 +apply plugin: 'com.android.application'
  25 +apply plugin: 'kotlin-android'
  26 +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
  27 +
  28 +android {
  29 + compileSdkVersion 29
  30 +
  31 + sourceSets {
  32 + main.java.srcDirs += 'src/main/kotlin'
  33 + }
  34 +
  35 + lintOptions {
  36 + disable 'InvalidPackage'
  37 + }
  38 +
  39 + defaultConfig {
  40 + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
  41 + applicationId "com.example.example"
  42 + minSdkVersion 16
  43 + targetSdkVersion 29
  44 + versionCode flutterVersionCode.toInteger()
  45 + versionName flutterVersionName
  46 + }
  47 +
  48 + buildTypes {
  49 + release {
  50 + // TODO: Add your own signing config for the release build.
  51 + // Signing with the debug keys for now, so `flutter run --release` works.
  52 + signingConfig signingConfigs.debug
  53 + }
  54 + }
  55 +}
  56 +
  57 +flutter {
  58 + source '../..'
  59 +}
  60 +
  61 +dependencies {
  62 + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
  63 +}
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.example.example">
  3 + <!-- Flutter needs it to communicate with the running application
  4 + to allow setting breakpoints, to provide hot reload, etc.
  5 + -->
  6 + <uses-permission android:name="android.permission.INTERNET"/>
  7 +</manifest>
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.example.example">
  3 + <application
  4 + android:label="example"
  5 + android:icon="@mipmap/ic_launcher">
  6 + <activity
  7 + android:name=".MainActivity"
  8 + android:launchMode="singleTop"
  9 + android:theme="@style/LaunchTheme"
  10 + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  11 + android:hardwareAccelerated="true"
  12 + android:windowSoftInputMode="adjustResize">
  13 + <!-- Specifies an Android theme to apply to this Activity as soon as
  14 + the Android process has started. This theme is visible to the user
  15 + while the Flutter UI initializes. After that, this theme continues
  16 + to determine the Window background behind the Flutter UI. -->
  17 + <meta-data
  18 + android:name="io.flutter.embedding.android.NormalTheme"
  19 + android:resource="@style/NormalTheme"
  20 + />
  21 + <!-- Displays an Android View that continues showing the launch screen
  22 + Drawable until Flutter paints its first frame, then this splash
  23 + screen fades out. A splash screen is useful to avoid any visual
  24 + gap between the end of Android's launch screen and the painting of
  25 + Flutter's first frame. -->
  26 + <meta-data
  27 + android:name="io.flutter.embedding.android.SplashScreenDrawable"
  28 + android:resource="@drawable/launch_background"
  29 + />
  30 + <intent-filter>
  31 + <action android:name="android.intent.action.MAIN"/>
  32 + <category android:name="android.intent.category.LAUNCHER"/>
  33 + </intent-filter>
  34 + </activity>
  35 + <!-- Don't delete the meta-data below.
  36 + This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
  37 + <meta-data
  38 + android:name="flutterEmbedding"
  39 + android:value="2" />
  40 + </application>
  41 +</manifest>
  1 +package com.example.example
  2 +
  3 +import io.flutter.embedding.android.FlutterActivity
  4 +
  5 +class MainActivity: FlutterActivity() {
  6 +}
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- Modify this file to customize your launch splash screen -->
  3 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <item android:drawable="?android:colorBackground" />
  5 +
  6 + <!-- You can insert your own image assets here -->
  7 + <!-- <item>
  8 + <bitmap
  9 + android:gravity="center"
  10 + android:src="@mipmap/launch_image" />
  11 + </item> -->
  12 +</layer-list>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- Modify this file to customize your launch splash screen -->
  3 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <item android:drawable="@android:color/white" />
  5 +
  6 + <!-- You can insert your own image assets here -->
  7 + <!-- <item>
  8 + <bitmap
  9 + android:gravity="center"
  10 + android:src="@mipmap/launch_image" />
  11 + </item> -->
  12 +</layer-list>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
  4 + <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
  5 + <!-- Show a splash screen on the activity. Automatically removed when
  6 + Flutter draws its first frame -->
  7 + <item name="android:windowBackground">@drawable/launch_background</item>
  8 + </style>
  9 + <!-- Theme applied to the Android Window as soon as the process has started.
  10 + This theme determines the color of the Android Window while your
  11 + Flutter UI initializes, as well as behind your Flutter UI while its
  12 + running.
  13 +
  14 + This Theme is only used starting with V2 of Flutter's Android embedding. -->
  15 + <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
  16 + <item name="android:windowBackground">?android:colorBackground</item>
  17 + </style>
  18 +</resources>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
  4 + <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
  5 + <!-- Show a splash screen on the activity. Automatically removed when
  6 + Flutter draws its first frame -->
  7 + <item name="android:windowBackground">@drawable/launch_background</item>
  8 + </style>
  9 + <!-- Theme applied to the Android Window as soon as the process has started.
  10 + This theme determines the color of the Android Window while your
  11 + Flutter UI initializes, as well as behind your Flutter UI while its
  12 + running.
  13 +
  14 + This Theme is only used starting with V2 of Flutter's Android embedding. -->
  15 + <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
  16 + <item name="android:windowBackground">?android:colorBackground</item>
  17 + </style>
  18 +</resources>
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.example.example">
  3 + <!-- Flutter needs it to communicate with the running application
  4 + to allow setting breakpoints, to provide hot reload, etc.
  5 + -->
  6 + <uses-permission android:name="android.permission.INTERNET"/>
  7 +</manifest>
  1 +buildscript {
  2 + ext.kotlin_version = '1.3.50'
  3 + repositories {
  4 + google()
  5 + jcenter()
  6 + }
  7 +
  8 + dependencies {
  9 + classpath 'com.android.tools.build:gradle:3.5.0'
  10 + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  11 + }
  12 +}
  13 +
  14 +allprojects {
  15 + repositories {
  16 + google()
  17 + jcenter()
  18 + }
  19 +}
  20 +
  21 +rootProject.buildDir = '../build'
  22 +subprojects {
  23 + project.buildDir = "${rootProject.buildDir}/${project.name}"
  24 +}
  25 +subprojects {
  26 + project.evaluationDependsOn(':app')
  27 +}
  28 +
  29 +task clean(type: Delete) {
  30 + delete rootProject.buildDir
  31 +}
  1 +org.gradle.jvmargs=-Xmx1536M
  2 +android.useAndroidX=true
  3 +android.enableJetifier=true
  1 +#Fri Jun 23 08:50:38 CEST 2017
  2 +distributionBase=GRADLE_USER_HOME
  3 +distributionPath=wrapper/dists
  4 +zipStoreBase=GRADLE_USER_HOME
  5 +zipStorePath=wrapper/dists
  6 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
  1 +include ':app'
  2 +
  3 +def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
  4 +def properties = new Properties()
  5 +
  6 +assert localPropertiesFile.exists()
  7 +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
  8 +
  9 +def flutterSdkPath = properties.getProperty("flutter.sdk")
  10 +assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
  11 +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
1 -import 'dart:async';  
2 -  
3 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
5 import 'routes/app_pages.dart'; 3 import 'routes/app_pages.dart';
1 -import 'package:dio/dio.dart';  
2 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
  2 +import '../data/home_api_provider.dart';
3 3
4 import '../data/home_repository.dart'; 4 import '../data/home_repository.dart';
5 import '../domain/adapters/repository_adapter.dart'; 5 import '../domain/adapters/repository_adapter.dart';
@@ -8,8 +8,8 @@ import '../presentation/controllers/home_controller.dart'; @@ -8,8 +8,8 @@ import '../presentation/controllers/home_controller.dart';
8 class HomeBinding extends Bindings { 8 class HomeBinding extends Bindings {
9 @override 9 @override
10 void dependencies() { 10 void dependencies() {
11 - Get.lazyPut(() => Dio());  
12 - Get.lazyPut<IHomeRepository>(() => HomeRepository(dio: Get.find())); 11 + Get.lazyPut<IHomeProvider>(() => HomeProvider());
  12 + Get.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find()));
13 Get.lazyPut(() => HomeController(homeRepository: Get.find())); 13 Get.lazyPut(() => HomeController(homeRepository: Get.find()));
14 } 14 }
15 } 15 }
  1 +import 'package:get/get.dart';
  2 +import '../domain/entity/cases_model.dart';
  3 +
  4 +// ignore: one_member_abstracts
  5 +abstract class IHomeProvider {
  6 + Future<Response<CasesModel>> getCases(String path);
  7 +}
  8 +
  9 +class HomeProvider extends GetConnect implements IHomeProvider {
  10 + @override
  11 + void onInit() {
  12 + httpClient.defaultDecoder = CasesModel.fromJson;
  13 + httpClient.baseUrl = 'https://api.covid19api.com';
  14 + }
  15 +
  16 + @override
  17 + Future<Response<CasesModel>> getCases(String path) => get(path);
  18 +}
1 -import 'package:dio/dio.dart';  
2 -  
3 import '../domain/adapters/repository_adapter.dart'; 1 import '../domain/adapters/repository_adapter.dart';
4 import '../domain/entity/cases_model.dart'; 2 import '../domain/entity/cases_model.dart';
  3 +import 'home_api_provider.dart';
5 4
6 class HomeRepository implements IHomeRepository { 5 class HomeRepository implements IHomeRepository {
7 - HomeRepository({this.dio});  
8 -  
9 - final Dio dio; 6 + HomeRepository({this.provider});
  7 + final IHomeProvider provider;
10 8
11 @override 9 @override
12 Future<CasesModel> getCases() async { 10 Future<CasesModel> getCases() async {
13 - try {  
14 - final response = await dio.get("https://api.covid19api.com/summary");  
15 - return CasesModel.fromJson(response.data as Map<String, dynamic>);  
16 - } on Exception catch (e) {  
17 - print(e.toString());  
18 - return Future.error(e.toString()); 11 + final cases = await provider.getCases("/summary");
  12 + if (cases.status.hasError) {
  13 + return Future.error(cases.statusText);
  14 + } else {
  15 + return cases.body;
19 } 16 }
20 } 17 }
21 } 18 }
@@ -15,12 +15,12 @@ class CasesModel { @@ -15,12 +15,12 @@ class CasesModel {
15 this.date, 15 this.date,
16 }); 16 });
17 17
18 - factory CasesModel.fromRawJson(String str) => 18 + static CasesModel fromRawJson(String str) =>
19 CasesModel.fromJson(json.decode(str) as Map<String, dynamic>); 19 CasesModel.fromJson(json.decode(str) as Map<String, dynamic>);
20 20
21 String toRawJson() => json.encode(toJson()); 21 String toRawJson() => json.encode(toJson());
22 22
23 - factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel( 23 + static CasesModel fromJson(dynamic json) => CasesModel(
24 global: json["Global"] == null 24 global: json["Global"] == null
25 ? null 25 ? null
26 : Global.fromJson(json["Global"] as Map<String, dynamic>), 26 : Global.fromJson(json["Global"] as Map<String, dynamic>),
  1 +flutter/ephemeral
  1 +cmake_minimum_required(VERSION 3.10)
  2 +project(runner LANGUAGES CXX)
  3 +
  4 +set(BINARY_NAME "example")
  5 +set(APPLICATION_ID "com.example.example")
  6 +
  7 +cmake_policy(SET CMP0063 NEW)
  8 +
  9 +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
  10 +
  11 +# Configure build options.
  12 +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  13 + set(CMAKE_BUILD_TYPE "Debug" CACHE
  14 + STRING "Flutter build mode" FORCE)
  15 + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
  16 + "Debug" "Profile" "Release")
  17 +endif()
  18 +
  19 +# Compilation settings that should be applied to most targets.
  20 +function(APPLY_STANDARD_SETTINGS TARGET)
  21 + target_compile_features(${TARGET} PUBLIC cxx_std_14)
  22 + target_compile_options(${TARGET} PRIVATE -Wall -Werror)
  23 + target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
  24 + target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
  25 +endfunction()
  26 +
  27 +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
  28 +
  29 +# Flutter library and tool build rules.
  30 +add_subdirectory(${FLUTTER_MANAGED_DIR})
  31 +
  32 +# System-level dependencies.
  33 +find_package(PkgConfig REQUIRED)
  34 +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
  35 +
  36 +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
  37 +
  38 +# Application build
  39 +add_executable(${BINARY_NAME}
  40 + "main.cc"
  41 + "my_application.cc"
  42 + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
  43 +)
  44 +apply_standard_settings(${BINARY_NAME})
  45 +target_link_libraries(${BINARY_NAME} PRIVATE flutter)
  46 +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
  47 +add_dependencies(${BINARY_NAME} flutter_assemble)
  48 +# Only the install-generated bundle's copy of the executable will launch
  49 +# correctly, since the resources must in the right relative locations. To avoid
  50 +# people trying to run the unbundled copy, put it in a subdirectory instead of
  51 +# the default top-level location.
  52 +set_target_properties(${BINARY_NAME}
  53 + PROPERTIES
  54 + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
  55 +)
  56 +
  57 +# Generated plugin build rules, which manage building the plugins and adding
  58 +# them to the application.
  59 +include(flutter/generated_plugins.cmake)
  60 +
  61 +
  62 +# === Installation ===
  63 +# By default, "installing" just makes a relocatable bundle in the build
  64 +# directory.
  65 +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
  66 +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  67 + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
  68 +endif()
  69 +
  70 +# Start with a clean build bundle directory every time.
  71 +install(CODE "
  72 + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
  73 + " COMPONENT Runtime)
  74 +
  75 +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
  76 +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
  77 +
  78 +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
  79 + COMPONENT Runtime)
  80 +
  81 +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
  82 + COMPONENT Runtime)
  83 +
  84 +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  85 + COMPONENT Runtime)
  86 +
  87 +if(PLUGIN_BUNDLED_LIBRARIES)
  88 + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
  89 + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  90 + COMPONENT Runtime)
  91 +endif()
  92 +
  93 +# Fully re-copy the assets directory on each build to avoid having stale files
  94 +# from a previous install.
  95 +set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
  96 +install(CODE "
  97 + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
  98 + " COMPONENT Runtime)
  99 +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
  100 + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
  101 +
  102 +# Install the AOT library on non-Debug builds only.
  103 +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
  104 + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  105 + COMPONENT Runtime)
  106 +endif()
  1 +cmake_minimum_required(VERSION 3.10)
  2 +
  3 +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
  4 +
  5 +# Configuration provided via flutter tool.
  6 +include(${EPHEMERAL_DIR}/generated_config.cmake)
  7 +
  8 +# TODO: Move the rest of this into files in ephemeral. See
  9 +# https://github.com/flutter/flutter/issues/57146.
  10 +
  11 +# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
  12 +# which isn't available in 3.10.
  13 +function(list_prepend LIST_NAME PREFIX)
  14 + set(NEW_LIST "")
  15 + foreach(element ${${LIST_NAME}})
  16 + list(APPEND NEW_LIST "${PREFIX}${element}")
  17 + endforeach(element)
  18 + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
  19 +endfunction()
  20 +
  21 +# === Flutter Library ===
  22 +# System-level dependencies.
  23 +find_package(PkgConfig REQUIRED)
  24 +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
  25 +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
  26 +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
  27 +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
  28 +
  29 +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
  30 +
  31 +# Published to parent scope for install step.
  32 +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
  33 +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
  34 +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
  35 +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
  36 +
  37 +list(APPEND FLUTTER_LIBRARY_HEADERS
  38 + "fl_basic_message_channel.h"
  39 + "fl_binary_codec.h"
  40 + "fl_binary_messenger.h"
  41 + "fl_dart_project.h"
  42 + "fl_engine.h"
  43 + "fl_json_message_codec.h"
  44 + "fl_json_method_codec.h"
  45 + "fl_message_codec.h"
  46 + "fl_method_call.h"
  47 + "fl_method_channel.h"
  48 + "fl_method_codec.h"
  49 + "fl_method_response.h"
  50 + "fl_plugin_registrar.h"
  51 + "fl_plugin_registry.h"
  52 + "fl_standard_message_codec.h"
  53 + "fl_standard_method_codec.h"
  54 + "fl_string_codec.h"
  55 + "fl_value.h"
  56 + "fl_view.h"
  57 + "flutter_linux.h"
  58 +)
  59 +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
  60 +add_library(flutter INTERFACE)
  61 +target_include_directories(flutter INTERFACE
  62 + "${EPHEMERAL_DIR}"
  63 +)
  64 +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
  65 +target_link_libraries(flutter INTERFACE
  66 + PkgConfig::GTK
  67 + PkgConfig::GLIB
  68 + PkgConfig::GIO
  69 + PkgConfig::BLKID
  70 +)
  71 +add_dependencies(flutter flutter_assemble)
  72 +
  73 +# === Flutter tool backend ===
  74 +# _phony_ is a non-existent file to force this command to run every time,
  75 +# since currently there's no way to get a full input/output list from the
  76 +# flutter tool.
  77 +add_custom_command(
  78 + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
  79 + ${CMAKE_CURRENT_BINARY_DIR}/_phony_
  80 + COMMAND ${CMAKE_COMMAND} -E env
  81 + ${FLUTTER_TOOL_ENVIRONMENT}
  82 + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
  83 + linux-x64 ${CMAKE_BUILD_TYPE}
  84 +)
  85 +add_custom_target(flutter_assemble DEPENDS
  86 + "${FLUTTER_LIBRARY}"
  87 + ${FLUTTER_LIBRARY_HEADERS}
  88 +)
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +#include "generated_plugin_registrant.h"
  6 +
  7 +
  8 +void fl_register_plugins(FlPluginRegistry* registry) {
  9 +}
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +#ifndef GENERATED_PLUGIN_REGISTRANT_
  6 +#define GENERATED_PLUGIN_REGISTRANT_
  7 +
  8 +#include <flutter_linux/flutter_linux.h>
  9 +
  10 +// Registers Flutter plugins.
  11 +void fl_register_plugins(FlPluginRegistry* registry);
  12 +
  13 +#endif // GENERATED_PLUGIN_REGISTRANT_
  1 +#
  2 +# Generated file, do not edit.
  3 +#
  4 +
  5 +list(APPEND FLUTTER_PLUGIN_LIST
  6 +)
  7 +
  8 +set(PLUGIN_BUNDLED_LIBRARIES)
  9 +
  10 +foreach(plugin ${FLUTTER_PLUGIN_LIST})
  11 + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
  12 + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
  13 + list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
  14 + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
  15 +endforeach(plugin)
  1 +#include "my_application.h"
  2 +
  3 +int main(int argc, char** argv) {
  4 + g_autoptr(MyApplication) app = my_application_new();
  5 + return g_application_run(G_APPLICATION(app), argc, argv);
  6 +}
  1 +#include "my_application.h"
  2 +
  3 +#include <flutter_linux/flutter_linux.h>
  4 +#ifdef GDK_WINDOWING_X11
  5 +#include <gdk/gdkx.h>
  6 +#endif
  7 +
  8 +#include "flutter/generated_plugin_registrant.h"
  9 +
  10 +struct _MyApplication {
  11 + GtkApplication parent_instance;
  12 + char** dart_entrypoint_arguments;
  13 +};
  14 +
  15 +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
  16 +
  17 +// Implements GApplication::activate.
  18 +static void my_application_activate(GApplication* application) {
  19 + MyApplication* self = MY_APPLICATION(application);
  20 + GtkWindow* window =
  21 + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
  22 +
  23 + // Use a header bar when running in GNOME as this is the common style used
  24 + // by applications and is the setup most users will be using (e.g. Ubuntu
  25 + // desktop).
  26 + // If running on X and not using GNOME then just use a traditional title bar
  27 + // in case the window manager does more exotic layout, e.g. tiling.
  28 + // If running on Wayland assume the header bar will work (may need changing
  29 + // if future cases occur).
  30 + gboolean use_header_bar = TRUE;
  31 +#ifdef GDK_WINDOWING_X11
  32 + GdkScreen *screen = gtk_window_get_screen(window);
  33 + if (GDK_IS_X11_SCREEN(screen)) {
  34 + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
  35 + if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
  36 + use_header_bar = FALSE;
  37 + }
  38 + }
  39 +#endif
  40 + if (use_header_bar) {
  41 + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
  42 + gtk_widget_show(GTK_WIDGET(header_bar));
  43 + gtk_header_bar_set_title(header_bar, "example");
  44 + gtk_header_bar_set_show_close_button(header_bar, TRUE);
  45 + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
  46 + }
  47 + else {
  48 + gtk_window_set_title(window, "example");
  49 + }
  50 +
  51 + gtk_window_set_default_size(window, 1280, 720);
  52 + gtk_widget_show(GTK_WIDGET(window));
  53 +
  54 + g_autoptr(FlDartProject) project = fl_dart_project_new();
  55 + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
  56 +
  57 + FlView* view = fl_view_new(project);
  58 + gtk_widget_show(GTK_WIDGET(view));
  59 + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
  60 +
  61 + fl_register_plugins(FL_PLUGIN_REGISTRY(view));
  62 +
  63 + gtk_widget_grab_focus(GTK_WIDGET(view));
  64 +}
  65 +
  66 +// Implements GApplication::local_command_line.
  67 +static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) {
  68 + MyApplication* self = MY_APPLICATION(application);
  69 + // Strip out the first argument as it is the binary name.
  70 + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
  71 +
  72 + g_autoptr(GError) error = nullptr;
  73 + if (!g_application_register(application, nullptr, &error)) {
  74 + g_warning("Failed to register: %s", error->message);
  75 + *exit_status = 1;
  76 + return TRUE;
  77 + }
  78 +
  79 + g_application_activate(application);
  80 + *exit_status = 0;
  81 +
  82 + return TRUE;
  83 +}
  84 +
  85 +// Implements GObject::dispose.
  86 +static void my_application_dispose(GObject *object) {
  87 + MyApplication* self = MY_APPLICATION(object);
  88 + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
  89 + G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
  90 +}
  91 +
  92 +static void my_application_class_init(MyApplicationClass* klass) {
  93 + G_APPLICATION_CLASS(klass)->activate = my_application_activate;
  94 + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
  95 + G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
  96 +}
  97 +
  98 +static void my_application_init(MyApplication* self) {}
  99 +
  100 +MyApplication* my_application_new() {
  101 + return MY_APPLICATION(g_object_new(my_application_get_type(),
  102 + "application-id", APPLICATION_ID,
  103 + nullptr));
  104 +}
  1 +#ifndef FLUTTER_MY_APPLICATION_H_
  2 +#define FLUTTER_MY_APPLICATION_H_
  3 +
  4 +#include <gtk/gtk.h>
  5 +
  6 +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
  7 + GtkApplication)
  8 +
  9 +/**
  10 + * my_application_new:
  11 + *
  12 + * Creates a new Flutter-based application.
  13 + *
  14 + * Returns: a new #MyApplication.
  15 + */
  16 +MyApplication* my_application_new();
  17 +
  18 +#endif // FLUTTER_MY_APPLICATION_H_
@@ -28,7 +28,6 @@ dependencies: @@ -28,7 +28,6 @@ dependencies:
28 # Use with the CupertinoIcons class for iOS style icons. 28 # Use with the CupertinoIcons class for iOS style icons.
29 get: 29 get:
30 path: ../ 30 path: ../
31 - dio: ^3.0.9  
32 get_test: ^3.13.3 31 get_test: ^3.13.3
33 32
34 dependency_overrides: 33 dependency_overrides:
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <!--
  5 + If you are serving your web app in a path other than the root, change the
  6 + href value below to reflect the base path you are serving from.
  7 +
  8 + The path provided below has to start and end with a slash "/" in order for
  9 + it to work correctly.
  10 +
  11 + Fore more details:
  12 + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
  13 + -->
  14 + <base href="/">
  15 +
  16 + <meta charset="UTF-8">
  17 + <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  18 + <meta name="description" content="A new Flutter project.">
  19 +
  20 + <!-- iOS meta tags & icons -->
  21 + <meta name="apple-mobile-web-app-capable" content="yes">
  22 + <meta name="apple-mobile-web-app-status-bar-style" content="black">
  23 + <meta name="apple-mobile-web-app-title" content="example">
  24 + <link rel="apple-touch-icon" href="icons/Icon-192.png">
  25 +
  26 + <!-- Favicon -->
  27 + <link rel="icon" type="image/png" href="favicon.png"/>
  28 +
  29 + <title>example</title>
  30 + <link rel="manifest" href="manifest.json">
  31 +</head>
  32 +<body>
  33 + <!-- This script installs service_worker.js to provide PWA functionality to
  34 + application. For more information, see:
  35 + https://developers.google.com/web/fundamentals/primers/service-workers -->
  36 + <script>
  37 + if ('serviceWorker' in navigator) {
  38 + window.addEventListener('flutter-first-frame', function () {
  39 + navigator.serviceWorker.register('flutter_service_worker.js');
  40 + });
  41 + }
  42 + </script>
  43 + <script src="main.dart.js" type="application/javascript"></script>
  44 +</body>
  45 +</html>
  1 +{
  2 + "name": "example",
  3 + "short_name": "example",
  4 + "start_url": ".",
  5 + "display": "standalone",
  6 + "background_color": "#0175C2",
  7 + "theme_color": "#0175C2",
  8 + "description": "A new Flutter project.",
  9 + "orientation": "portrait-primary",
  10 + "prefer_related_applications": false,
  11 + "icons": [
  12 + {
  13 + "src": "icons/Icon-192.png",
  14 + "sizes": "192x192",
  15 + "type": "image/png"
  16 + },
  17 + {
  18 + "src": "icons/Icon-512.png",
  19 + "sizes": "512x512",
  20 + "type": "image/png"
  21 + }
  22 + ]
  23 +}
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 /// injection, and route management in a quick and practical way. 3 /// injection, and route management in a quick and practical way.
4 library get; 4 library get;
5 5
  6 +export 'get_connect/connect.dart';
6 export 'get_core/get_core.dart'; 7 export 'get_core/get_core.dart';
7 export 'get_instance/get_instance.dart'; 8 export 'get_instance/get_instance.dart';
8 export 'get_navigation/get_navigation.dart'; 9 export 'get_navigation/get_navigation.dart';
  1 +import '../get_instance/src/lifecycle.dart';
  2 +import 'http/src/certificates/certificates.dart';
  3 +import 'http/src/http.dart';
  4 +import 'http/src/response/response.dart';
  5 +import 'sockets/sockets.dart';
  6 +
  7 +export 'http/src/certificates/certificates.dart';
  8 +export 'http/src/http.dart';
  9 +export 'http/src/multipart/form_data.dart';
  10 +export 'http/src/multipart/multipart_file.dart';
  11 +export 'http/src/response/response.dart';
  12 +export 'sockets/sockets.dart';
  13 +
  14 +abstract class GetConnectInterface with GetLifeCycleBase {
  15 + List<GetSocket> sockets;
  16 + GetHttpClient get httpClient;
  17 +
  18 + Future<Response<T>> get<T>(
  19 + String url, {
  20 + Map<String, String> headers,
  21 + String contentType,
  22 + Map<String, dynamic> query,
  23 + Decoder<T> decoder,
  24 + });
  25 + Future<Response<T>> post<T>(
  26 + String url,
  27 + dynamic body, {
  28 + String contentType,
  29 + Map<String, String> headers,
  30 + Map<String, dynamic> query,
  31 + });
  32 +
  33 + Future<Response<T>> put<T>(
  34 + String url,
  35 + Map<String, dynamic> body, {
  36 + String contentType,
  37 + Map<String, String> headers,
  38 + Map<String, dynamic> query,
  39 + });
  40 +
  41 + Future<Response<T>> delete<T>(
  42 + String url, {
  43 + Map<String, String> headers,
  44 + String contentType,
  45 + Map<String, dynamic> query,
  46 + });
  47 +
  48 + GetSocket socket(String url, {Duration ping = const Duration(seconds: 5)});
  49 +}
  50 +
  51 +class GetConnect extends GetConnectInterface {
  52 + GetConnect({
  53 + this.userAgent = 'getx-client',
  54 + this.timeout = const Duration(seconds: 5),
  55 + this.followRedirects = true,
  56 + this.maxRedirects = 5,
  57 + this.maxAuthRetries = 1,
  58 + this.allowAutoSignedCert = false,
  59 + }) {
  60 + $configureLifeCycle();
  61 + }
  62 +
  63 + bool allowAutoSignedCert;
  64 + String userAgent;
  65 + String baseUrl;
  66 + String defaultContentType = 'application/json; charset=utf-8';
  67 + bool followRedirects;
  68 + int maxRedirects;
  69 + int maxAuthRetries;
  70 + Decoder defaultDecoder;
  71 + Duration timeout;
  72 + List<TrustedCertificate> trustedCertificates;
  73 + GetHttpClient _httpClient;
  74 + List<GetSocket> _sockets;
  75 +
  76 + @override
  77 + List<GetSocket> get sockets => _sockets ??= <GetSocket>[];
  78 +
  79 + @override
  80 + GetHttpClient get httpClient => _httpClient ??= GetHttpClient(
  81 + userAgent: userAgent,
  82 + timeout: timeout,
  83 + followRedirects: followRedirects,
  84 + maxRedirects: maxRedirects,
  85 + maxAuthRetries: maxAuthRetries,
  86 + allowAutoSignedCert: allowAutoSignedCert,
  87 + baseUrl: baseUrl,
  88 + trustedCertificates: trustedCertificates,
  89 + );
  90 +
  91 + @override
  92 + Future<Response<T>> get<T>(
  93 + String url, {
  94 + Map<String, String> headers,
  95 + String contentType,
  96 + Map<String, dynamic> query,
  97 + Decoder<T> decoder,
  98 + }) {
  99 + _checkIfDisposed();
  100 + return httpClient.get(
  101 + url,
  102 + headers: headers,
  103 + contentType: contentType,
  104 + query: query,
  105 + decoder: decoder,
  106 + );
  107 + }
  108 +
  109 + @override
  110 + Future<Response<T>> post<T>(
  111 + String url,
  112 + dynamic body, {
  113 + String contentType,
  114 + Map<String, String> headers,
  115 + Map<String, dynamic> query,
  116 + Decoder<T> decoder,
  117 + }) {
  118 + _checkIfDisposed();
  119 + return httpClient.post<T>(
  120 + url,
  121 + body,
  122 + headers: headers,
  123 + contentType: contentType,
  124 + query: query,
  125 + decoder: decoder,
  126 + );
  127 + }
  128 +
  129 + @override
  130 + Future<Response<T>> put<T>(
  131 + String url,
  132 + Map<String, dynamic> body, {
  133 + String contentType,
  134 + Map<String, String> headers,
  135 + Map<String, dynamic> query,
  136 + Decoder<T> decoder,
  137 + }) {
  138 + _checkIfDisposed();
  139 + return httpClient.put(
  140 + url,
  141 + body,
  142 + headers: headers,
  143 + contentType: contentType,
  144 + query: query,
  145 + decoder: decoder,
  146 + );
  147 + }
  148 +
  149 + @override
  150 + Future<Response<T>> delete<T>(
  151 + String url, {
  152 + Map<String, String> headers,
  153 + String contentType,
  154 + Map<String, dynamic> query,
  155 + Decoder<T> decoder,
  156 + }) {
  157 + _checkIfDisposed();
  158 + return httpClient.delete(
  159 + url,
  160 + headers: headers,
  161 + contentType: contentType,
  162 + query: query,
  163 + decoder: decoder,
  164 + );
  165 + }
  166 +
  167 + @override
  168 + GetSocket socket(String url, {Duration ping = const Duration(seconds: 5)}) {
  169 + _checkIfDisposed(isHttp: false);
  170 + final _url = baseUrl == null ? url : baseUrl + url;
  171 + final _socket = GetSocket(_url, ping: ping);
  172 + sockets.add(_socket);
  173 + return _socket;
  174 + }
  175 +
  176 + bool _isDisposed = false;
  177 +
  178 + bool get isDisposed => _isDisposed;
  179 +
  180 + void _checkIfDisposed({bool isHttp = true}) {
  181 + if (_isDisposed) {
  182 + throw 'Can not emit events to disposed clients';
  183 + }
  184 + }
  185 +
  186 + void dispose() {
  187 + if (_sockets != null) {
  188 + for (var socket in sockets) {
  189 + socket.close();
  190 + }
  191 + _sockets?.clear();
  192 + sockets = null;
  193 + }
  194 + if (_httpClient != null) {
  195 + httpClient.close();
  196 + _httpClient = null;
  197 + }
  198 + _isDisposed = true;
  199 + }
  200 +}
  1 +class TrustedCertificate {
  2 + final List<int> bytes;
  3 +
  4 + TrustedCertificate(this.bytes);
  5 +}
  1 +class GetHttpException implements Exception {
  2 + final String message;
  3 +
  4 + final Uri uri;
  5 +
  6 + GetHttpException(this.message, [this.uri]);
  7 +
  8 + @override
  9 + String toString() => message;
  10 +}
  11 +
  12 +class UnauthorizedException implements Exception {
  13 + @override
  14 + String toString() {
  15 + return 'Operation Unauthorized';
  16 + }
  17 +}
  18 +
  19 +class UnexpectedFormat implements Exception {
  20 + final String message;
  21 + UnexpectedFormat(this.message);
  22 + @override
  23 + String toString() {
  24 + return 'Unexpected format: $message';
  25 + }
  26 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +import 'package:meta/meta.dart';
  4 +
  5 +import '../src/certificates/certificates.dart';
  6 +import '../src/exceptions/exceptions.dart';
  7 +import '../src/http_impl/http_request_stub.dart'
  8 + if (dart.library.html) 'http_impl/http_request_html.dart'
  9 + if (dart.library.io) 'http_impl/http_request_io.dart';
  10 +import '../src/http_impl/request_base.dart';
  11 +import '../src/interceptors/get_interceptors.dart';
  12 +import '../src/multipart/form_data.dart';
  13 +import '../src/request/request.dart';
  14 +import '../src/response/response.dart';
  15 +import '../src/status/http_status.dart';
  16 +
  17 +typedef Decoder<T> = T Function(dynamic data);
  18 +
  19 +class GetHttpClient {
  20 + String userAgent;
  21 + String baseUrl;
  22 +
  23 + String defaultContentType = 'application/json; charset=utf-8';
  24 +
  25 + bool followRedirects;
  26 + int maxRedirects;
  27 + int maxAuthRetries;
  28 +
  29 + Decoder defaultDecoder;
  30 +
  31 + Duration timeout;
  32 +
  33 + final HttpRequestBase _httpClient;
  34 +
  35 + final GetModifier _interceptor;
  36 +
  37 + GetHttpClient({
  38 + this.userAgent = 'getx-client',
  39 + this.timeout = const Duration(seconds: 8),
  40 + this.followRedirects = true,
  41 + this.maxRedirects = 5,
  42 + this.maxAuthRetries = 1,
  43 + bool allowAutoSignedCert = false,
  44 + this.baseUrl,
  45 + List<TrustedCertificate> trustedCertificates,
  46 + }) : _httpClient = HttpRequestImpl(
  47 + allowAutoSignedCert: allowAutoSignedCert,
  48 + trustedCertificates: trustedCertificates,
  49 + ),
  50 + _interceptor = GetModifier();
  51 +
  52 + Uri _createUri(String url, Map<String, dynamic> query) {
  53 + if (baseUrl != null) {
  54 + url = baseUrl + url;
  55 + }
  56 + final uri = Uri.parse(url);
  57 + if (query != null) {
  58 + uri.replace(queryParameters: query);
  59 + }
  60 + return uri;
  61 + }
  62 +
  63 + Future<Request<T>> _requestWithBody<T>(
  64 + String url,
  65 + String contentType,
  66 + dynamic body,
  67 + String method,
  68 + Map<String, dynamic> query,
  69 + Decoder<T> decoder,
  70 + ) async {
  71 + assert(method != null);
  72 + assert(body != null);
  73 +
  74 + List<int> bodyBytes;
  75 +
  76 + if (body is FormData) {
  77 + bodyBytes = await body.readAsBytes();
  78 + } else {
  79 + try {
  80 + var jsonString = json.encode(body);
  81 +
  82 + //TODO check this implementation
  83 + if (contentType != null) {
  84 + if (contentType.toLowerCase() ==
  85 + 'application/x-www-form-urlencoded') {
  86 + var paramName = 'param';
  87 + jsonString = '$paramName=${Uri.encodeQueryComponent(jsonString)}';
  88 + }
  89 + }
  90 +
  91 + bodyBytes = utf8.encode(jsonString);
  92 + } on Exception catch (err) {
  93 + throw UnexpectedFormat(err.toString());
  94 + }
  95 + }
  96 +
  97 + final bodyStream = BodyBytes.fromBytes(bodyBytes);
  98 +
  99 + final headers = <String, String>{};
  100 +
  101 + _setHeadersWithBody(contentType, headers, bodyBytes);
  102 +
  103 + final uri = _createUri(url, query);
  104 +
  105 + return Request(
  106 + method: method,
  107 + url: uri,
  108 + headers: headers,
  109 + bodyBytes: bodyStream,
  110 + followRedirects: followRedirects,
  111 + maxRedirects: maxRedirects,
  112 + );
  113 + }
  114 +
  115 + void _setHeadersWithBody(
  116 + String contentType,
  117 + // String jsonString,
  118 + Map<String, String> headers,
  119 + List<int> bodyBytes,
  120 + // List<MultipartFile> files,
  121 + ) {
  122 + // if (files != null) {
  123 + // headers['content-type'] = 'multipart/form-data';
  124 + // headers['x-requested-with'] = 'XMLHttpRequest';
  125 + // } else {
  126 + // headers['content-type'] = contentType ?? defaultContentType;
  127 + // }
  128 +
  129 + headers['content-type'] =
  130 + contentType ?? defaultContentType; // verify if this is better location
  131 +
  132 + headers['user-agent'] = userAgent;
  133 + headers['content-length'] = bodyBytes.length.toString();
  134 + }
  135 +
  136 + void _setSimpleHeaders(
  137 + Map<String, String> headers,
  138 + String contentType,
  139 + ) {
  140 + headers['content-type'] = contentType ?? defaultContentType;
  141 + headers['user-agent'] = userAgent;
  142 + }
  143 +
  144 + Future<Response<T>> _performRequest<T>(
  145 + HandlerExecute<T> handler, {
  146 + bool authenticate = false,
  147 + int requestNumber = 1,
  148 + Map<String, String> headers,
  149 + }) async {
  150 + try {
  151 + var request = await handler();
  152 +
  153 + headers?.forEach((key, value) {
  154 + request.headers[key] = value;
  155 + });
  156 +
  157 + if (authenticate) await _interceptor.authenticator(request);
  158 + await _interceptor.modifyRequest(request);
  159 +
  160 + var response = await _httpClient.send<T>(request);
  161 +
  162 + await _interceptor.modifyResponse(request, response);
  163 +
  164 + if (HttpStatus.unauthorized == response.statusCode &&
  165 + _interceptor.authenticator != null &&
  166 + requestNumber <= maxAuthRetries) {
  167 + return _performRequest(
  168 + handler,
  169 + authenticate: true,
  170 + requestNumber: requestNumber + 1,
  171 + headers: request.headers,
  172 + );
  173 + } else if (HttpStatus.unauthorized == response.statusCode) {
  174 + throw UnauthorizedException();
  175 + }
  176 +
  177 + return response;
  178 + } on Exception catch (err) {
  179 + throw GetHttpException(err.toString());
  180 + }
  181 + }
  182 +
  183 + Future<Request<T>> _get<T>(
  184 + String url,
  185 + String contentType,
  186 + Map<String, dynamic> query,
  187 + Decoder<T> decoder,
  188 + ) {
  189 + final headers = <String, String>{};
  190 + _setSimpleHeaders(headers, contentType);
  191 + final uri = _createUri(url, query);
  192 +
  193 + return Future.value(Request<T>(
  194 + method: 'get',
  195 + url: uri,
  196 + headers: headers,
  197 + decoder: decoder ?? (defaultDecoder as Decoder<T>),
  198 + ));
  199 + }
  200 +
  201 + Future<Request<T>> _post<T>(
  202 + String url, {
  203 + String contentType,
  204 + @required dynamic body,
  205 + Map<String, dynamic> query,
  206 + Decoder<T> decoder,
  207 + // List<MultipartFile> files,
  208 + }) {
  209 + assert(body != null);
  210 + return _requestWithBody<T>(
  211 + url,
  212 + contentType,
  213 + body,
  214 + 'post',
  215 + query,
  216 + decoder,
  217 + );
  218 + }
  219 +
  220 + Future<Request<T>> _put<T>(
  221 + String url, {
  222 + String contentType,
  223 + @required dynamic body,
  224 + @required Map<String, dynamic> query,
  225 + Decoder<T> decoder,
  226 + // List<MultipartFile> files,
  227 + }) {
  228 + assert(body != null);
  229 + return _requestWithBody(url, contentType, body, 'put', query, decoder);
  230 + }
  231 +
  232 + Request<T> _delete<T>(
  233 + String url,
  234 + String contentType,
  235 + Map<String, dynamic> query,
  236 + Decoder<T> decoder,
  237 + ) {
  238 + final headers = <String, String>{};
  239 + _setSimpleHeaders(headers, contentType);
  240 + final uri = _createUri(url, query);
  241 +
  242 + return Request<T>(
  243 + method: 'delete', url: uri, headers: headers, decoder: decoder);
  244 + }
  245 +
  246 + Future<Response<T>> post<T>(
  247 + String url,
  248 + dynamic body, {
  249 + String contentType,
  250 + Map<String, String> headers,
  251 + Map<String, dynamic> query,
  252 + Decoder<T> decoder,
  253 + // List<MultipartFile> files,
  254 + }) async {
  255 + try {
  256 + var response = await _performRequest<T>(
  257 + () => _post<T>(
  258 + url,
  259 + contentType: contentType,
  260 + body: body,
  261 + query: query,
  262 + decoder: decoder,
  263 + // files: files,
  264 + ),
  265 + headers: headers,
  266 + );
  267 + return response;
  268 + } on Exception catch (e) {
  269 + return Future.value(Response<T>(
  270 + request: null,
  271 + statusCode: null,
  272 + body: null,
  273 + statusText: 'Can not connect to server. Reason: $e',
  274 + ));
  275 + }
  276 + }
  277 +
  278 + Future<Response<T>> put<T>(
  279 + String url,
  280 + Map<String, dynamic> body, {
  281 + String contentType,
  282 + Map<String, String> headers,
  283 + Map<String, dynamic> query,
  284 + Decoder<T> decoder,
  285 + }) async {
  286 + try {
  287 + var response = await _performRequest(
  288 + () => _put(
  289 + url,
  290 + contentType: contentType,
  291 + query: query,
  292 + body: body,
  293 + decoder: decoder,
  294 + ),
  295 + headers: headers,
  296 + );
  297 + return response;
  298 + } on Exception catch (e) {
  299 + return Future.value(Response<T>(
  300 + request: null,
  301 + statusCode: null,
  302 + body: null,
  303 + statusText: 'Can not connect to server. Reason: $e',
  304 + ));
  305 + }
  306 + }
  307 +
  308 + Future<Response<T>> get<T>(
  309 + String url, {
  310 + Map<String, String> headers,
  311 + String contentType,
  312 + Map<String, dynamic> query,
  313 + Decoder<T> decoder,
  314 + }) async {
  315 + try {
  316 + var response = await _performRequest<T>(
  317 + () => _get<T>(url, contentType, query, decoder),
  318 + headers: headers,
  319 + );
  320 + return response;
  321 + } on Exception catch (e) {
  322 + return Future.value(Response<T>(
  323 + request: null,
  324 + statusCode: null,
  325 + body: null,
  326 + statusText: 'Can not connect to server. Reason: $e',
  327 + ));
  328 + }
  329 + }
  330 +
  331 + Future<Response<T>> delete<T>(
  332 + String url, {
  333 + Map<String, String> headers,
  334 + String contentType,
  335 + Map<String, dynamic> query,
  336 + Decoder<T> decoder,
  337 + }) async {
  338 + try {
  339 + var response = await _performRequest(
  340 + () async => _delete<T>(url, contentType, query, decoder),
  341 + headers: headers,
  342 + );
  343 + return response;
  344 + } on Exception catch (e) {
  345 + return Future.value(Response<T>(
  346 + request: null,
  347 + statusCode: null,
  348 + body: null,
  349 + statusText: 'Can not connect to server. Reason: $e',
  350 + ));
  351 + }
  352 + }
  353 +
  354 + void close() {
  355 + _httpClient.close();
  356 + }
  357 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +import 'dart:html' as html;
  4 +import 'dart:typed_data';
  5 +
  6 +import '../certificates/certificates.dart';
  7 +import '../exceptions/exceptions.dart';
  8 +import '../request/request.dart';
  9 +import '../response/response.dart';
  10 +import 'request_base.dart';
  11 +
  12 +/// A `dart:html` implementation of `HttpRequestBase`.
  13 +class HttpRequestImpl implements HttpRequestBase {
  14 + HttpRequestImpl({
  15 + bool allowAutoSignedCert = true,
  16 + List<TrustedCertificate> trustedCertificates,
  17 + });
  18 +
  19 + /// The currently active XHRs.
  20 + final _xhrs = <html.HttpRequest>{};
  21 +
  22 + ///This option requires that you submit credentials for requests
  23 + ///on different sites. The default is false
  24 + bool withCredentials = false;
  25 +
  26 + /// Sends an HTTP request and asynchronously returns the response.
  27 + @override
  28 + Future<Response<T>> send<T>(Request<T> request) async {
  29 + var bytes = await request.bodyBytes.toBytes();
  30 + html.HttpRequest xhr;
  31 +
  32 + // if (request.files != null) {
  33 + // var data = html.FormData();
  34 + // if (request.files != null) {
  35 + // for (MultipartFile element in request.files) {
  36 + // var stream = element.finalize();
  37 + // data.appendBlob(element., html.File(element.finalize(),
  38 + // element.filename),
  39 + // element.filename);
  40 + // }
  41 + // }
  42 +
  43 + // xhr = await html.HttpRequest.request('${request.url}',
  44 + // method: request.method, sendData: data);
  45 + // } else {
  46 + // xhr = html.HttpRequest()
  47 + // ..open(request.method, '${request.url}', async: true);
  48 + // }
  49 +
  50 + xhr = html.HttpRequest()
  51 + ..open(request.method, '${request.url}', async: true); // check this
  52 +
  53 + _xhrs.add(xhr);
  54 +
  55 + xhr
  56 + ..responseType = 'blob'
  57 + ..withCredentials = withCredentials;
  58 + request.headers.forEach(xhr.setRequestHeader);
  59 +
  60 + var completer = Completer<Response<T>>();
  61 + xhr.onLoad.first.then((_) {
  62 + var blob = xhr.response as html.Blob ?? html.Blob([]);
  63 + var reader = html.FileReader();
  64 +
  65 + reader.onLoad.first.then((_) async {
  66 + var bodyBytes = BodyBytes.fromBytes(reader.result as Uint8List);
  67 +
  68 + final stringBody =
  69 + await bodyBytesToString(bodyBytes, xhr.responseHeaders);
  70 +
  71 + T body;
  72 + try {
  73 + if (request.decoder == null) {
  74 + body = jsonDecode(stringBody) as T;
  75 + } else {
  76 + body = request.decoder(jsonDecode(stringBody));
  77 + }
  78 + // body = request.decoder(stringBody);
  79 + } on Exception catch (_) {
  80 + body = stringBody as T;
  81 + }
  82 +
  83 + // final body = jsonDecode(stringBody);
  84 +
  85 + final response = Response<T>(
  86 + bodyBytes: bodyBytes,
  87 + statusCode: xhr.status,
  88 + request: request,
  89 + headers: xhr.responseHeaders,
  90 + statusText: xhr.statusText,
  91 + body: body,
  92 + );
  93 + completer.complete(response);
  94 + });
  95 +
  96 + reader.onError.first.then((error) {
  97 + completer.completeError(
  98 + GetHttpException(error.toString(), request.url),
  99 + StackTrace.current,
  100 + );
  101 + });
  102 +
  103 + reader.readAsArrayBuffer(blob);
  104 + });
  105 +
  106 + xhr.onError.first.then((_) {
  107 + completer.completeError(
  108 + GetHttpException('XMLHttpRequest error.', request.url),
  109 + StackTrace.current);
  110 + });
  111 +
  112 + xhr.send(bytes);
  113 +
  114 + try {
  115 + return await completer.future;
  116 + } finally {
  117 + _xhrs.remove(xhr);
  118 + }
  119 + }
  120 +
  121 + /// Closes the client and abort all active requests.
  122 + @override
  123 + void close() {
  124 + for (var xhr in _xhrs) {
  125 + xhr.abort();
  126 + }
  127 + }
  128 +}
  1 +import 'dart:convert';
  2 +import 'dart:io' as io;
  3 +
  4 +import '../certificates/certificates.dart';
  5 +import '../exceptions/exceptions.dart';
  6 +import '../request/request.dart';
  7 +import '../response/response.dart';
  8 +import 'request_base.dart';
  9 +
  10 +/// A `dart:io` implementation of `HttpRequestBase`.
  11 +class HttpRequestImpl extends HttpRequestBase {
  12 + io.HttpClient _httpClient;
  13 + io.SecurityContext _securityContext;
  14 +
  15 + HttpRequestImpl({
  16 + bool allowAutoSignedCert = true,
  17 + List<TrustedCertificate> trustedCertificates,
  18 + }) {
  19 + _httpClient = io.HttpClient();
  20 + if (trustedCertificates != null) {
  21 + _securityContext = io.SecurityContext();
  22 + for (final trustedCertificate in trustedCertificates) {
  23 + _securityContext
  24 + .setTrustedCertificatesBytes(List.from(trustedCertificate.bytes));
  25 + }
  26 + }
  27 +
  28 + _httpClient = io.HttpClient(context: _securityContext);
  29 + _httpClient.badCertificateCallback = (_, __, ___) => allowAutoSignedCert;
  30 + }
  31 +
  32 + @override
  33 + Future<Response<T>> send<T>(Request<T> request) async {
  34 + var requestBody = await request.bodyBytes.toBytes();
  35 + var stream = BodyBytes.fromBytes(requestBody ?? const []);
  36 +
  37 + try {
  38 + var ioRequest = (await _httpClient.openUrl(request.method, request.url))
  39 + ..followRedirects = request.followRedirects
  40 + ..persistentConnection = request.persistentConnection
  41 + ..maxRedirects = request.maxRedirects
  42 + ..contentLength = requestBody.length ?? -1;
  43 + request.headers.forEach(ioRequest.headers.set);
  44 +
  45 + var response = await stream.pipe(ioRequest) as io.HttpClientResponse;
  46 +
  47 + var headers = <String, String>{};
  48 + response.headers.forEach((key, values) {
  49 + headers[key] = values.join(',');
  50 + });
  51 +
  52 + final bodyBytes = BodyBytes(response);
  53 +
  54 + final stringBody = await bodyBytesToString(bodyBytes, headers);
  55 +
  56 + T body;
  57 + try {
  58 + if (request.decoder == null) {
  59 + body = jsonDecode(stringBody) as T;
  60 + } else {
  61 + body = request.decoder(jsonDecode(stringBody));
  62 + }
  63 + } on Exception catch (_) {
  64 + body = stringBody as T;
  65 + }
  66 +
  67 + return Response(
  68 + headers: headers,
  69 + request: request,
  70 + statusCode: response.statusCode,
  71 + statusText: response.reasonPhrase,
  72 + bodyBytes: bodyBytes,
  73 + body: body,
  74 + );
  75 + } on io.HttpException catch (error) {
  76 + throw GetHttpException(error.message, error.uri);
  77 + }
  78 + }
  79 +
  80 + /// Closes the HttpClient.
  81 + @override
  82 + void close() {
  83 + if (_httpClient != null) {
  84 + _httpClient.close(force: true);
  85 + _httpClient = null;
  86 + }
  87 + }
  88 +}
  89 +
  90 +extension FileExt on io.FileSystemEntity {
  91 + String get fileName {
  92 + return this?.path?.split(io.Platform.pathSeparator)?.last;
  93 + }
  94 +}
  1 +import '../certificates/certificates.dart';
  2 +import '../request/request.dart';
  3 +import '../response/response.dart';
  4 +import 'request_base.dart';
  5 +
  6 +class HttpRequestImpl extends HttpRequestBase {
  7 + HttpRequestImpl({
  8 + bool allowAutoSignedCert = true,
  9 + List<TrustedCertificate> trustedCertificates,
  10 + });
  11 + @override
  12 + void close() {}
  13 +
  14 + @override
  15 + Future<Response<T>> send<T>(Request<T> request) {
  16 + throw UnimplementedError();
  17 + }
  18 +}
  1 +import '../request/request.dart';
  2 +import '../response/response.dart';
  3 +
  4 +/// Abstract interface of [HttpRequestImpl].
  5 +abstract class HttpRequestBase {
  6 + /// Sends an HTTP [Request].
  7 + Future<Response<T>> send<T>(Request<T> request);
  8 +
  9 + /// Closes the [Request] and cleans up any resources associated with it.
  10 + void close();
  11 +}
  1 +import '../request/request.dart';
  2 +import '../response/response.dart';
  3 +
  4 +typedef RequestModifier = Future<Request> Function(Request request);
  5 +
  6 +typedef ResponseModifier = Future<Null> Function(
  7 + Request request, Response response);
  8 +
  9 +typedef HandlerExecute<T> = Future<Request<T>> Function();
  10 +
  11 +class GetModifier {
  12 + final _requestModifiers = <RequestModifier>[];
  13 + final _responseModifiers = <ResponseModifier>[];
  14 + RequestModifier authenticator;
  15 +
  16 + void addRequestModifier(RequestModifier interceptor) {
  17 + _requestModifiers.add(interceptor);
  18 + }
  19 +
  20 + void removeRequestModifier(RequestModifier interceptor) {
  21 + _requestModifiers.remove(interceptor);
  22 + }
  23 +
  24 + void addResponseModifier(ResponseModifier interceptor) {
  25 + _responseModifiers.add(interceptor);
  26 + }
  27 +
  28 + void removeResponseModifier(ResponseModifier interceptor) {
  29 + _requestModifiers.remove(interceptor);
  30 + }
  31 +
  32 + Future<void> modifyRequest(Request request) async {
  33 + if (_requestModifiers.isNotEmpty) {
  34 + for (var interceptor in _requestModifiers) {
  35 + await interceptor(request);
  36 + }
  37 + }
  38 + }
  39 +
  40 + Future<void> modifyResponse(Request request, Response response) async {
  41 + if (_responseModifiers.isNotEmpty) {
  42 + for (var interceptor in _responseModifiers) {
  43 + await interceptor(request, response);
  44 + }
  45 + }
  46 + }
  47 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +import 'dart:math';
  4 +import '../../../../get_rx/src/rx_stream/rx_stream.dart';
  5 +
  6 +import '../utils/utils.dart';
  7 +
  8 +import 'multipart_file.dart';
  9 +
  10 +class FormData {
  11 + static const _BOUNDARY_LENGTH = GET_BOUNDARY.length + 10;
  12 +
  13 + final String boundary;
  14 +
  15 + /// The boundary of FormData, it consists of a constant prefix and a random
  16 + /// postfix to assure the the boundary unpredictable and unique, each FormData
  17 + /// instance will be different.
  18 +
  19 + final _newlineRegExp = RegExp(r'\r\n|\r|\n');
  20 +
  21 + /// The form fields to send for this request.
  22 + final fields = <MapEntry<String, String>>[];
  23 +
  24 + /// The [files].
  25 + final files = <MapEntry<String, MultipartFile>>[];
  26 +
  27 + /// Whether [finalize] has been called.
  28 + bool get isFinalized => _isFinalized;
  29 + bool _isFinalized = false;
  30 +
  31 + FormData(Map<String, dynamic> map)
  32 + : boundary = GET_BOUNDARY +
  33 + Random().nextInt(4294967296).toString().padLeft(10, '0') {
  34 + encodeMap(
  35 + map,
  36 + (key, value) {
  37 + if (value == null) return null;
  38 + if (value is MultipartFile) {
  39 + files.add(MapEntry(key, value));
  40 + } else {
  41 + fields.add(MapEntry(key, value.toString()));
  42 + }
  43 + return null;
  44 + },
  45 + encode: false,
  46 + );
  47 + }
  48 +
  49 + /// Returns the header string for a field. The return value is guaranteed to
  50 + /// contain only ASCII characters.
  51 + String _headerForField(String name, String value) {
  52 + var header =
  53 + 'content-disposition: form-data; name="${_browserEncode(name)}"';
  54 + if (!isPlainAscii(value)) {
  55 + header = '$header\r\n'
  56 + 'content-type: text/plain; charset=utf-8\r\n'
  57 + 'content-transfer-encoding: binary';
  58 + }
  59 + return '$header\r\n\r\n';
  60 + }
  61 +
  62 + /// Returns the header string for a file. The return value is guaranteed to
  63 + /// contain only ASCII characters.
  64 + String _headerForFile(MapEntry<String, MultipartFile> entry) {
  65 + var file = entry.value;
  66 + var header =
  67 + 'content-disposition: form-data; name="${_browserEncode(entry.key)}"';
  68 + if (file.filename != null) {
  69 + header = '$header; filename="${_browserEncode(file.filename)}"';
  70 + }
  71 + header = '$header\r\n'
  72 + 'content-type: ${file.contentType}';
  73 + return '$header\r\n\r\n';
  74 + }
  75 +
  76 + /// Encode [value] in the same way browsers do.
  77 + String _browserEncode(String value) {
  78 + // http://tools.ietf.org/html/rfc2388 mandates some complex encodings for
  79 + // field names and file names, but in practice user agents seem not to
  80 + // follow this at all. Instead, they URL-encode `\r`, `\n`, and `\r\n` as
  81 + // `\r\n`; URL-encode `"`; and do nothing else (even for `%` or non-ASCII
  82 + // characters). We follow their behavior.
  83 + return value.replaceAll(_newlineRegExp, '%0D%0A').replaceAll('"', '%22');
  84 + }
  85 +
  86 + /// The total length of the request body, in bytes. This is calculated from
  87 + /// [fields] and [files] and cannot be set manually.
  88 + int get length {
  89 + var length = 0;
  90 +
  91 + for (final item in fields) {
  92 + length += '--'.length +
  93 + _BOUNDARY_LENGTH +
  94 + '\r\n'.length +
  95 + utf8.encode(_headerForField(item.key, item.value)).length +
  96 + utf8.encode(item.value).length +
  97 + '\r\n'.length;
  98 + }
  99 +
  100 + for (var file in files) {
  101 + length += '--'.length +
  102 + _BOUNDARY_LENGTH +
  103 + '\r\n'.length +
  104 + utf8.encode(_headerForFile(file)).length +
  105 + file.value.length +
  106 + '\r\n'.length;
  107 + }
  108 +
  109 + return length + '--'.length + _BOUNDARY_LENGTH + '--\r\n'.length;
  110 + }
  111 +
  112 + Stream<List<int>> finalize() {
  113 + if (isFinalized) {
  114 + throw StateError("Can't finalize a finalized MultipartFile.");
  115 + }
  116 + _isFinalized = true;
  117 + final getStream = GetStream<List<int>>();
  118 +
  119 + for (final item in fields) {
  120 + stringToBytes('--$boundary\r\n', getStream);
  121 + stringToBytes(_headerForField(item.key, item.value), getStream);
  122 + stringToBytes(item.value, getStream);
  123 + writeLine(getStream);
  124 + }
  125 +
  126 + Future.forEach<MapEntry<String, MultipartFile>>(files, (file) {
  127 + stringToBytes('--$boundary\r\n', getStream);
  128 + stringToBytes(_headerForFile(file), getStream);
  129 +
  130 + return streamToFuture(file.value.stream, getStream)
  131 + .then((_) => writeLine(getStream));
  132 + }).then((_) {
  133 + stringToBytes('--$boundary--\r\n', getStream);
  134 + getStream.close();
  135 + });
  136 + return getStream.stream;
  137 + }
  138 +
  139 + ///Transform the entire FormData contents as a list of bytes asynchronously.
  140 + Future<List<int>> readAsBytes() {
  141 + return Future(() => finalize().reduce((a, b) => [...a, ...b]));
  142 + }
  143 +}
  1 +class MultipartFile {
  2 + final String contentType;
  3 +
  4 + final Stream<List<int>> _stream;
  5 +
  6 + final int length;
  7 +
  8 + final String filename;
  9 +
  10 + MultipartFile(
  11 + List<int> bytes, {
  12 + this.filename,
  13 + this.contentType = 'application/octet-stream',
  14 + }) : length = bytes.length,
  15 + _stream = Stream.fromIterable([bytes]);
  16 +
  17 + Stream<List<int>> get stream => _stream;
  18 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +import 'dart:typed_data';
  4 +
  5 +import 'package:meta/meta.dart';
  6 +
  7 +import '../http.dart';
  8 +import '../multipart/form_data.dart';
  9 +
  10 +class Request<T> {
  11 + /// Headers attach to this [Request]
  12 + final Map<String, String> headers;
  13 +
  14 + /// The [Uri] from request
  15 + final Uri url;
  16 +
  17 + final Decoder<T> decoder;
  18 +
  19 + /// The Http Method from this [Request]
  20 + /// ex: `GET`,`POST`,`PUT`,`DELETE`
  21 + final String method;
  22 +
  23 + /// The BodyBytes of body from this [Request]
  24 + final BodyBytes bodyBytes;
  25 +
  26 + /// When true, the client will follow redirects to resolves this [Request]
  27 + final bool followRedirects;
  28 +
  29 + /// The maximum number of redirects if [followRedirects] is true.
  30 + final int maxRedirects;
  31 +
  32 + final bool persistentConnection;
  33 +
  34 + final FormData files;
  35 +
  36 + const Request._({
  37 + @required this.method,
  38 + @required this.bodyBytes,
  39 + @required this.url,
  40 + @required this.headers,
  41 + @required this.followRedirects,
  42 + @required this.maxRedirects,
  43 + @required this.files,
  44 + @required this.persistentConnection,
  45 + @required this.decoder,
  46 + });
  47 +
  48 + factory Request({
  49 + @required Uri url,
  50 + @required String method,
  51 + @required Map<String, String> headers,
  52 + BodyBytes bodyBytes,
  53 + bool followRedirects = true,
  54 + int maxRedirects = 4,
  55 + FormData files,
  56 + bool persistentConnection = true,
  57 + final Decoder<T> decoder,
  58 + }) {
  59 + assert(url != null);
  60 + assert(method != null);
  61 + assert(followRedirects != null);
  62 + if (followRedirects) {
  63 + assert(maxRedirects != null);
  64 + assert(maxRedirects > 0);
  65 + }
  66 + return Request._(
  67 + url: url,
  68 + method: method,
  69 + bodyBytes: bodyBytes ??= BodyBytes.fromBytes(const []),
  70 + headers: Map.from(headers ??= <String, String>{}),
  71 + followRedirects: followRedirects,
  72 + maxRedirects: maxRedirects,
  73 + files: files,
  74 + persistentConnection: persistentConnection,
  75 + decoder: decoder,
  76 + );
  77 + }
  78 +
  79 + /// Constructs a [Request] containing the same properties as [request].
  80 + factory Request.copyWith(Request request) => Request(
  81 + method: request.method,
  82 + url: request.url,
  83 + headers: request.headers,
  84 + bodyBytes: request.bodyBytes,
  85 + followRedirects: request.followRedirects,
  86 + maxRedirects: request.maxRedirects,
  87 + files: request.files,
  88 + persistentConnection: request.persistentConnection,
  89 + );
  90 +}
  91 +
  92 +class BodyBytes extends StreamView<List<int>> {
  93 + BodyBytes(Stream<List<int>> stream) : super(stream);
  94 +
  95 + factory BodyBytes.fromBytes(List<int> bytes) =>
  96 + BodyBytes(Stream.fromIterable([bytes]));
  97 +
  98 + Future<Uint8List> toBytes() {
  99 + var completer = Completer<Uint8List>();
  100 + var sink = ByteConversionSink.withCallback(
  101 + (bytes) => completer.complete(
  102 + Uint8List.fromList(bytes),
  103 + ),
  104 + );
  105 + listen(sink.add,
  106 + onError: completer.completeError,
  107 + onDone: sink.close,
  108 + cancelOnError: true);
  109 + return completer.future;
  110 + }
  111 +
  112 + Future<String> bytesToString([Encoding encoding = utf8]) =>
  113 + encoding.decodeStream(this);
  114 +
  115 + Stream<String> toStringStream([Encoding encoding = utf8]) =>
  116 + encoding.decoder.bind(this);
  117 +}
  1 +import 'dart:collection';
  2 +import 'dart:convert';
  3 +
  4 +import 'package:flutter/foundation.dart';
  5 +import 'package:meta/meta.dart';
  6 +
  7 +import '../request/request.dart';
  8 +import '../status/http_status.dart';
  9 +
  10 +class Response<T> {
  11 + const Response({
  12 + @required this.request,
  13 + @required this.statusCode,
  14 + // ignore: always_require_non_null_named_parameters
  15 + this.bodyBytes,
  16 + this.statusText = '',
  17 + this.headers = const {},
  18 + @required this.body,
  19 + });
  20 +
  21 + /// The Http [Request] linked with this [Response].
  22 + final Request request;
  23 +
  24 + /// The response headers.
  25 + final Map<String, String> headers;
  26 +
  27 + /// The status code returned by the server.
  28 + final int statusCode;
  29 +
  30 + /// Human-readable context for [statusCode].
  31 + final String statusText;
  32 +
  33 + /// [HttpStatus] from [Response]. `status.connectionError` is true
  34 + /// when statusCode is null. `status.isUnauthorized` is true when
  35 + /// statusCode is equal `401`. `status.isNotFound` is true when
  36 + /// statusCode is equal `404`. `status.isServerError` is true when
  37 + /// statusCode is between `500` and `599`.
  38 + HttpStatus get status => HttpStatus(statusCode);
  39 +
  40 + /// `hasError` is true when statusCode is not between 200 and 299.
  41 + bool get hasError => status.hasError;
  42 +
  43 + /// `isOk` is true when statusCode is between 200 and 299.
  44 + bool get isOk => !hasError;
  45 +
  46 + /// `unauthorized` is true when statusCode is equal `401`.
  47 + bool get unauthorized => status.isUnauthorized;
  48 +
  49 + /// The response body as a Stream of Bytes.
  50 + final BodyBytes bodyBytes;
  51 +
  52 + /// The decoded body of this [Response]. You can access the
  53 + /// body parameters as Map
  54 + /// Ex: body['title'];
  55 + final T body;
  56 +}
  57 +
  58 +Future<String> bodyBytesToString(
  59 + BodyBytes bodyBytes, Map<String, String> headers) {
  60 + return bodyBytes.bytesToString(_encodingForHeaders(headers));
  61 +}
  62 +
  63 +/// Returns the encoding to use for a response with the given headers.
  64 +///
  65 +/// Defaults to [latin1] if the headers don't specify a charset or if that
  66 +/// charset is unknown.
  67 +Encoding _encodingForHeaders(Map<String, String> headers) =>
  68 + _encodingForCharset(_contentTypeForHeaders(headers).parameters['charset']);
  69 +
  70 +/// Returns the [Encoding] that corresponds to [charset].
  71 +///
  72 +/// Returns [fallback] if [charset] is null or if no [Encoding] was found that
  73 +/// corresponds to [charset].
  74 +Encoding _encodingForCharset(String charset, [Encoding fallback = latin1]) {
  75 + if (charset == null) return fallback;
  76 + return Encoding.getByName(charset) ?? fallback;
  77 +}
  78 +
  79 +/// Returns the [MediaType] object for the given headers's content-type.
  80 +///
  81 +/// Defaults to `application/octet-stream`.
  82 +HeaderValue _contentTypeForHeaders(Map<String, String> headers) {
  83 + var contentType = headers['content-type'];
  84 + if (contentType != null) return HeaderValue.parse(contentType);
  85 + return HeaderValue('application/octet-stream');
  86 +}
  87 +
  88 +class HeaderValue {
  89 + String _value;
  90 + Map<String, String> _parameters;
  91 + Map<String, String> _unmodifiableParameters;
  92 +
  93 + HeaderValue([this._value = '', Map<String, String> parameters]) {
  94 + if (parameters != null) {
  95 + _parameters = HashMap<String, String>.from(parameters);
  96 + }
  97 + }
  98 +
  99 + static HeaderValue parse(String value,
  100 + {String parameterSeparator = ';',
  101 + String valueSeparator,
  102 + bool preserveBackslash = false}) {
  103 + var result = HeaderValue();
  104 + result._parse(value, parameterSeparator, valueSeparator, preserveBackslash);
  105 + return result;
  106 + }
  107 +
  108 + String get value => _value;
  109 +
  110 + void _ensureParameters() {
  111 + _parameters ??= HashMap<String, String>();
  112 + }
  113 +
  114 + Map<String, String> get parameters {
  115 + _ensureParameters();
  116 + _unmodifiableParameters ??= UnmodifiableMapView(_parameters);
  117 + return _unmodifiableParameters;
  118 + }
  119 +
  120 + @override
  121 + String toString() {
  122 + var sb = StringBuffer();
  123 + sb.write(_value);
  124 + if (parameters != null && parameters.isNotEmpty) {
  125 + _parameters.forEach((name, value) {
  126 + sb..write('; ')..write(name)..write('=')..write(value);
  127 + });
  128 + }
  129 + return sb.toString();
  130 + }
  131 +
  132 + void _parse(String value, String parameterSeparator, String valueSeparator,
  133 + bool preserveBackslash) {
  134 + var index = 0;
  135 +
  136 + bool done() => index == value.length;
  137 +
  138 + void skipWS() {
  139 + while (!done()) {
  140 + if (value[index] != ' ' && value[index] != '\t') return;
  141 + index++;
  142 + }
  143 + }
  144 +
  145 + String parseValue() {
  146 + var start = index;
  147 + while (!done()) {
  148 + if (value[index] == ' ' ||
  149 + value[index] == '\t' ||
  150 + value[index] == valueSeparator ||
  151 + value[index] == parameterSeparator) {
  152 + break;
  153 + }
  154 + index++;
  155 + }
  156 + return value.substring(start, index);
  157 + }
  158 +
  159 + void expect(String expected) {
  160 + if (done() || value[index] != expected) {
  161 + throw StateError('Failed to parse header value');
  162 + }
  163 + index++;
  164 + }
  165 +
  166 + void maybeExpect(String expected) {
  167 + if (value[index] == expected) index++;
  168 + }
  169 +
  170 + void parseParameters() {
  171 + var parameters = HashMap<String, String>();
  172 + _parameters = UnmodifiableMapView(parameters);
  173 +
  174 + String parseParameterName() {
  175 + var start = index;
  176 + while (!done()) {
  177 + if (value[index] == ' ' ||
  178 + value[index] == '\t' ||
  179 + value[index] == '=' ||
  180 + value[index] == parameterSeparator ||
  181 + value[index] == valueSeparator) {
  182 + break;
  183 + }
  184 + index++;
  185 + }
  186 + return value.substring(start, index).toLowerCase();
  187 + }
  188 +
  189 + String parseParameterValue() {
  190 + if (!done() && value[index] == '\"') {
  191 + var sb = StringBuffer();
  192 + index++;
  193 + while (!done()) {
  194 + if (value[index] == '\\') {
  195 + if (index + 1 == value.length) {
  196 + throw StateError('Failed to parse header value');
  197 + }
  198 + if (preserveBackslash && value[index + 1] != '\"') {
  199 + sb.write(value[index]);
  200 + }
  201 + index++;
  202 + } else if (value[index] == '\"') {
  203 + index++;
  204 + break;
  205 + }
  206 + sb.write(value[index]);
  207 + index++;
  208 + }
  209 + return sb.toString();
  210 + } else {
  211 + var val = parseValue();
  212 + return val == '' ? null : val;
  213 + }
  214 + }
  215 +
  216 + while (!done()) {
  217 + skipWS();
  218 + if (done()) return;
  219 + var name = parseParameterName();
  220 + skipWS();
  221 + if (done()) {
  222 + parameters[name] = null;
  223 + return;
  224 + }
  225 + maybeExpect('=');
  226 + skipWS();
  227 + if (done()) {
  228 + parameters[name] = null;
  229 + return;
  230 + }
  231 + var value = parseParameterValue();
  232 + if (name == 'charset' && value != null) {
  233 + value = value.toLowerCase();
  234 + }
  235 + parameters[name] = value;
  236 + skipWS();
  237 + if (done()) return;
  238 + if (value[index] == valueSeparator) return;
  239 + expect(parameterSeparator);
  240 + }
  241 + }
  242 +
  243 + skipWS();
  244 + _value = parseValue();
  245 + skipWS();
  246 + if (done()) return;
  247 + maybeExpect(parameterSeparator);
  248 + parseParameters();
  249 + }
  250 +}
  1 +class HttpStatus {
  2 + HttpStatus(this.code);
  3 + final int code;
  4 +
  5 + static const int continue_ = 100;
  6 + static const int switchingProtocols = 101;
  7 + static const int processing = 102;
  8 + static const int ok = 200;
  9 + static const int created = 201;
  10 + static const int accepted = 202;
  11 + static const int nonAuthoritativeInformation = 203;
  12 + static const int noContent = 204;
  13 + static const int resetContent = 205;
  14 + static const int partialContent = 206;
  15 + static const int multiStatus = 207;
  16 + static const int alreadyReported = 208;
  17 + static const int imUsed = 226;
  18 + static const int multipleChoices = 300;
  19 + static const int movedPermanently = 301;
  20 + static const int found = 302;
  21 + static const int movedTemporarily = 302; // Common alias for found.
  22 + static const int seeOther = 303;
  23 + static const int notModified = 304;
  24 + static const int useProxy = 305;
  25 + static const int temporaryRedirect = 307;
  26 + static const int permanentRedirect = 308;
  27 + static const int badRequest = 400;
  28 + static const int unauthorized = 401;
  29 + static const int paymentRequired = 402;
  30 + static const int forbidden = 403;
  31 + static const int notFound = 404;
  32 + static const int methodNotAllowed = 405;
  33 + static const int notAcceptable = 406;
  34 + static const int proxyAuthenticationRequired = 407;
  35 + static const int requestTimeout = 408;
  36 + static const int conflict = 409;
  37 + static const int gone = 410;
  38 + static const int lengthRequired = 411;
  39 + static const int preconditionFailed = 412;
  40 + static const int requestEntityTooLarge = 413;
  41 + static const int requestUriTooLong = 414;
  42 + static const int unsupportedMediaType = 415;
  43 + static const int requestedRangeNotSatisfiable = 416;
  44 + static const int expectationFailed = 417;
  45 + static const int misdirectedRequest = 421;
  46 + static const int unprocessableEntity = 422;
  47 + static const int locked = 423;
  48 + static const int failedDependency = 424;
  49 + static const int upgradeRequired = 426;
  50 + static const int preconditionRequired = 428;
  51 + static const int tooManyRequests = 429;
  52 + static const int requestHeaderFieldsTooLarge = 431;
  53 + static const int connectionClosedWithoutResponse = 444;
  54 + static const int unavailableForLegalReasons = 451;
  55 + static const int clientClosedRequest = 499;
  56 + static const int internalServerError = 500;
  57 + static const int notImplemented = 501;
  58 + static const int badGateway = 502;
  59 + static const int serviceUnavailable = 503;
  60 + static const int gatewayTimeout = 504;
  61 + static const int httpVersionNotSupported = 505;
  62 + static const int variantAlsoNegotiates = 506;
  63 + static const int insufficientStorage = 507;
  64 + static const int loopDetected = 508;
  65 + static const int notExtended = 510;
  66 + static const int networkAuthenticationRequired = 511;
  67 + static const int networkConnectTimeoutError = 599;
  68 +
  69 + bool get connectionError => code == null;
  70 +
  71 + bool get isUnauthorized => code == unauthorized;
  72 +
  73 + bool get isForbidden => code == forbidden;
  74 +
  75 + bool get isNotFound => code == notFound;
  76 +
  77 + bool get isServerError =>
  78 + between(internalServerError, networkConnectTimeoutError);
  79 +
  80 + bool between(int begin, int end) {
  81 + return !connectionError && code >= begin && code <= end;
  82 + }
  83 +
  84 + bool get isOk => between(200, 299);
  85 +
  86 + bool get hasError => !isOk;
  87 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +
  4 +import '../../../../get_rx/src/rx_stream/rx_stream.dart';
  5 +
  6 +import '../request/request.dart';
  7 +
  8 +bool isTokenChar(int byte) {
  9 + return byte > 31 && byte < 128 && !SEPARATOR_MAP[byte];
  10 +}
  11 +
  12 +bool isValueChar(int byte) {
  13 + return (byte > 31 && byte < 128) ||
  14 + (byte == CharCode.SP) ||
  15 + (byte == CharCode.HT);
  16 +}
  17 +
  18 +class CharCode {
  19 + static const int HT = 9;
  20 + static const int LF = 10;
  21 + static const int CR = 13;
  22 + static const int SP = 32;
  23 + static const int COMMA = 44;
  24 + static const int SLASH = 47;
  25 + static const int ZERO = 48;
  26 + static const int ONE = 49;
  27 + static const int COLON = 58;
  28 + static const int SEMI_COLON = 59;
  29 +}
  30 +
  31 +const bool F = false;
  32 +
  33 +const String GET_BOUNDARY = '--get-boundary-';
  34 +
  35 +const bool T = true;
  36 +const SEPARATOR_MAP = [
  37 + F, F, F, F, F, F, F, F, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  38 + F, F, F, F, F, F, F, F, T, F, T, F, F, F, F, F, T, T, F, F, T, F, F, T, //
  39 + F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, F, F, F, F, F, F, F, //
  40 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, T, T, F, F, //
  41 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  42 + F, F, F, T, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  43 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  44 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  45 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  46 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
  47 + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F
  48 +];
  49 +
  50 +String validateField(String field) {
  51 + for (var i = 0; i < field.length; i++) {
  52 + if (!isTokenChar(field.codeUnitAt(i))) {
  53 + throw FormatException(
  54 + 'Invalid HTTP header field name: ${json.encode(field)}', field, i);
  55 + }
  56 + }
  57 + return field.toLowerCase();
  58 +}
  59 +
  60 +BodyBytes toBodyBytes(Stream<List<int>> stream) {
  61 + if (stream is BodyBytes) return stream;
  62 + return BodyBytes(stream);
  63 +}
  64 +
  65 +final _asciiOnly = RegExp(r'^[\x00-\x7F]+$');
  66 +
  67 +/// Returns whether [string] is composed entirely of ASCII-compatible
  68 +/// characters.
  69 +bool isPlainAscii(String string) => _asciiOnly.hasMatch(string);
  70 +
  71 +String encodeMap(dynamic data, _Handler handler, {bool encode = true}) {
  72 + return urlEncode(data, '', encode, handler).toString();
  73 +}
  74 +
  75 +StringBuffer urlEncode(
  76 + dynamic sub,
  77 + String path,
  78 + bool encode,
  79 + _Handler handler,
  80 +) {
  81 + var urlData = StringBuffer('');
  82 + var first = true;
  83 + var leftBracket = '[';
  84 + var rightBracket = ']';
  85 +
  86 + if (encode) {
  87 + leftBracket = '%5B';
  88 + rightBracket = '%5D';
  89 + }
  90 +
  91 + var encodeComponent = encode ? Uri.encodeQueryComponent : (e) => e;
  92 + if (sub is List) {
  93 + for (var i = 0; i < sub.length; i++) {
  94 + urlEncode(
  95 + sub[i],
  96 + // ignore: lines_longer_than_80_chars
  97 + '$path$leftBracket${(sub[i] is Map || sub[i] is List) ? i : ''}$rightBracket',
  98 + encode,
  99 + handler);
  100 + }
  101 + } else if (sub is Map) {
  102 + sub.forEach((key, value) {
  103 + if (path == '') {
  104 + urlEncode(
  105 + value,
  106 + '${encodeComponent(key as String)}',
  107 + encode,
  108 + handler,
  109 + );
  110 + } else {
  111 + urlEncode(
  112 + value,
  113 + '$path$leftBracket${encodeComponent(key as String)}$rightBracket',
  114 + encode,
  115 + handler,
  116 + );
  117 + }
  118 + });
  119 + } else {
  120 + var str = handler(path, sub);
  121 + var isNotEmpty = str != null && (str as String).trim().isNotEmpty;
  122 + if (!first && isNotEmpty) {
  123 + urlData.write('&');
  124 + }
  125 + first = false;
  126 + if (isNotEmpty) {
  127 + urlData.write(str);
  128 + }
  129 + }
  130 +
  131 + return urlData;
  132 +}
  133 +
  134 +Future streamToFuture(Stream stream, GetStream sink) {
  135 + var completer = Completer();
  136 + stream.listen(sink.add,
  137 + onError: sink.addError, onDone: () => completer.complete());
  138 + return completer.future;
  139 +}
  140 +
  141 +void stringToBytes(String string, GetStream stream) {
  142 + stream.add(utf8.encode(string));
  143 +}
  144 +
  145 +void writeLine(GetStream stream) => stream.add([13, 10]);
  146 +
  147 +typedef _Handler = Function(String key, Object value);
  1 +import 'src/sockets_stub.dart'
  2 + if (dart.library.html) 'src/sockets_html.dart'
  3 + if (dart.library.io) 'src/sockets_io.dart';
  4 +
  5 +class GetSocket extends BaseWebSocket {
  6 + GetSocket(
  7 + String url, {
  8 + Duration ping = const Duration(seconds: 5),
  9 + }) : super(url, ping: ping);
  10 +}
  1 +import 'dart:convert';
  2 +
  3 +class Close {
  4 + final String message;
  5 + final int reason;
  6 +
  7 + Close(this.message, this.reason);
  8 +
  9 + @override
  10 + String toString() {
  11 + return 'Closed by server [$reason => $message]!';
  12 + }
  13 +}
  14 +
  15 +typedef OpenSocket = void Function();
  16 +
  17 +typedef CloseSocket = void Function(Close);
  18 +
  19 +typedef MessageSocket = void Function(dynamic val);
  20 +
  21 +class SocketNotifier {
  22 + var _onMessages = <MessageSocket>[];
  23 + var _onEvents = <String, MessageSocket>{};
  24 + var _onCloses = <CloseSocket>[];
  25 + var _onErrors = <CloseSocket>[];
  26 +
  27 + OpenSocket open;
  28 +
  29 + void addMessages(MessageSocket socket) {
  30 + _onMessages.add((socket));
  31 + }
  32 +
  33 + void addEvents(String event, MessageSocket socket) {
  34 + _onEvents[event] = socket;
  35 + }
  36 +
  37 + void addCloses(CloseSocket socket) {
  38 + _onCloses.add(socket);
  39 + }
  40 +
  41 + void addErrors(CloseSocket socket) {
  42 + _onErrors.add((socket));
  43 + }
  44 +
  45 + void notifyData(dynamic data) {
  46 + for (var item in _onMessages) {
  47 + item(data);
  48 + }
  49 + if (data is String) {
  50 + _tryOn(data);
  51 + }
  52 + }
  53 +
  54 + void notifyClose(Close err) {
  55 + for (var item in _onCloses) {
  56 + item(err);
  57 + }
  58 + }
  59 +
  60 + void notifyError(Close err) {
  61 + // rooms.removeWhere((key, value) => value.contains(_ws));
  62 + for (var item in _onErrors) {
  63 + item(err);
  64 + }
  65 + }
  66 +
  67 + void _tryOn(String message) {
  68 + try {
  69 + var msg = jsonDecode(message);
  70 + final event = msg['type'];
  71 + final data = msg['data'];
  72 + if (_onEvents.containsKey(event)) {
  73 + _onEvents[event](data);
  74 + }
  75 + } on Exception catch (_) {
  76 + return;
  77 + }
  78 + }
  79 +
  80 + void dispose() {
  81 + _onMessages = null;
  82 + _onEvents = null;
  83 + _onCloses = null;
  84 + _onErrors = null;
  85 + }
  86 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +// ignore: avoid_web_libraries_in_flutter
  4 +import 'dart:html';
  5 +
  6 +import '../../../get_core/get_core.dart';
  7 +
  8 +import 'socket_notifier.dart';
  9 +
  10 +enum ConnectionStatus {
  11 + connecting,
  12 + connected,
  13 + closed,
  14 +}
  15 +
  16 +class BaseWebSocket {
  17 + String url;
  18 + WebSocket socket;
  19 + SocketNotifier socketNotifier = SocketNotifier();
  20 + Duration ping;
  21 + bool isDisposed = false;
  22 +
  23 + BaseWebSocket(this.url, {this.ping = const Duration(seconds: 5)}) {
  24 + url = url.startsWith('https')
  25 + ? url.replaceAll('https:', 'wss:')
  26 + : url.replaceAll('http:', 'ws:');
  27 + }
  28 + ConnectionStatus connectionStatus;
  29 + Timer _t;
  30 +
  31 + void connect() {
  32 + try {
  33 + connectionStatus = ConnectionStatus.connecting;
  34 + socket = WebSocket(url);
  35 + socket.onOpen.listen((e) {
  36 + socketNotifier?.open();
  37 + _t = Timer?.periodic(ping, (t) {
  38 + socket.send('');
  39 + });
  40 + connectionStatus = ConnectionStatus.connected;
  41 + });
  42 +
  43 + socket.onMessage.listen((event) {
  44 + socketNotifier.notifyData(event.data);
  45 + });
  46 +
  47 + socket.onClose.listen((e) {
  48 + _t?.cancel();
  49 +
  50 + connectionStatus = ConnectionStatus.closed;
  51 + socketNotifier.notifyClose(Close(e.reason, e.code));
  52 + });
  53 + socket.onError.listen((event) {
  54 + _t?.cancel();
  55 + socketNotifier.notifyError(Close(event.toString(), 0));
  56 + connectionStatus = ConnectionStatus.closed;
  57 + });
  58 + } on Exception catch (e) {
  59 + _t?.cancel();
  60 + socketNotifier.notifyError(Close(e.toString(), 500));
  61 + connectionStatus = ConnectionStatus.closed;
  62 + // close(500, e.toString());
  63 + }
  64 + }
  65 +
  66 + // ignore: use_setters_to_change_properties
  67 + void onOpen(OpenSocket fn) {
  68 + socketNotifier.open = fn;
  69 + }
  70 +
  71 + void onClose(CloseSocket fn) {
  72 + socketNotifier.addCloses(fn);
  73 + }
  74 +
  75 + void onError(CloseSocket fn) {
  76 + socketNotifier.addErrors(fn);
  77 + }
  78 +
  79 + void onMessage(MessageSocket fn) {
  80 + socketNotifier.addMessages(fn);
  81 + }
  82 +
  83 + void on(String event, MessageSocket message) {
  84 + socketNotifier.addEvents(event, message);
  85 + }
  86 +
  87 + void close([int status, String reason]) {
  88 + if (socket != null) socket.close(status, reason);
  89 + }
  90 +
  91 + void send(dynamic data) {
  92 + if (connectionStatus == ConnectionStatus.closed) {
  93 + connect();
  94 + }
  95 + if (socket != null && socket.readyState == WebSocket.OPEN) {
  96 + socket.send(data);
  97 + } else {
  98 + Get.log('WebSocket not connected, message $data not sent');
  99 + }
  100 + }
  101 +
  102 + void emit(String event, dynamic data) {
  103 + send(jsonEncode({'type': event, 'data': data}));
  104 + }
  105 +
  106 + void dispose() {
  107 + socketNotifier.dispose();
  108 + socketNotifier = null;
  109 + isDisposed = true;
  110 + }
  111 +}
  1 +import 'dart:async';
  2 +import 'dart:convert';
  3 +import 'dart:io';
  4 +import 'dart:math';
  5 +
  6 +import '../../../get_core/get_core.dart';
  7 +
  8 +import 'socket_notifier.dart';
  9 +
  10 +enum ConnectionStatus {
  11 + connecting,
  12 + connected,
  13 + closed,
  14 +}
  15 +
  16 +class BaseWebSocket {
  17 + String url;
  18 + WebSocket socket;
  19 + SocketNotifier socketNotifier = SocketNotifier();
  20 + bool isDisposed = false;
  21 + BaseWebSocket(this.url, {this.ping = const Duration(seconds: 5)});
  22 + Duration ping;
  23 + bool allowSelfSigned = true;
  24 +
  25 + ConnectionStatus connectionStatus;
  26 +
  27 + Future connect() async {
  28 + if (isDisposed) {
  29 + socketNotifier = SocketNotifier();
  30 + }
  31 + try {
  32 + connectionStatus = ConnectionStatus.connecting;
  33 + socket = allowSelfSigned
  34 + ? await _connectForSelfSignedCert(url)
  35 + : await WebSocket.connect(url);
  36 +
  37 + socket.pingInterval = ping;
  38 + socketNotifier?.open();
  39 + connectionStatus = ConnectionStatus.connected;
  40 +
  41 + socket.listen((data) {
  42 + socketNotifier.notifyData(data);
  43 + }, onError: (err) {
  44 + socketNotifier.notifyError(Close(err.toString(), 1005));
  45 + }, onDone: () {
  46 + connectionStatus = ConnectionStatus.closed;
  47 + socketNotifier
  48 + .notifyClose(Close('Connection Closed', socket.closeCode));
  49 + }, cancelOnError: true);
  50 + return;
  51 + } on SocketException catch (e) {
  52 + connectionStatus = ConnectionStatus.closed;
  53 + socketNotifier.notifyError(Close(e.osError.message, e.osError.errorCode));
  54 + return;
  55 + }
  56 + }
  57 +
  58 + // ignore: use_setters_to_change_properties
  59 + void onOpen(OpenSocket fn) {
  60 + socketNotifier.open = fn;
  61 + }
  62 +
  63 + void onClose(CloseSocket fn) {
  64 + socketNotifier.addCloses(fn);
  65 + }
  66 +
  67 + void onError(CloseSocket fn) {
  68 + socketNotifier.addErrors(fn);
  69 + }
  70 +
  71 + void onMessage(MessageSocket fn) {
  72 + socketNotifier.addMessages(fn);
  73 + }
  74 +
  75 + void on(String event, MessageSocket message) {
  76 + socketNotifier.addEvents(event, message);
  77 + }
  78 +
  79 + void close([int status, String reason]) {
  80 + if (socket != null) {
  81 + socket.close(status, reason);
  82 + }
  83 + }
  84 +
  85 + void send(dynamic data) async {
  86 + if (connectionStatus == ConnectionStatus.closed) {
  87 + await connect();
  88 + }
  89 +
  90 + if (socket != null) {
  91 + socket.add(data);
  92 + }
  93 + }
  94 +
  95 + void dispose() {
  96 + socketNotifier.dispose();
  97 + socketNotifier = null;
  98 + isDisposed = true;
  99 + }
  100 +
  101 + void emit(String event, dynamic data) {
  102 + send(jsonEncode({'type': event, 'data': data}));
  103 + }
  104 +
  105 + Future<WebSocket> _connectForSelfSignedCert(String url) async {
  106 + try {
  107 + var r = Random();
  108 + var key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
  109 + var client = HttpClient(context: SecurityContext());
  110 + client.badCertificateCallback = (cert, host, port) {
  111 + Get.log(
  112 + 'BaseWebSocket: Allow self-signed certificate => $host:$port. ');
  113 + return true;
  114 + };
  115 +
  116 + var request = await client.getUrl(Uri.parse(url));
  117 + request.headers.add('Connection', 'Upgrade');
  118 + request.headers.add('Upgrade', 'websocket');
  119 + request.headers.add('Sec-WebSocket-Version', '13');
  120 + request.headers.add('Sec-WebSocket-Key', key.toLowerCase());
  121 +
  122 + var response = await request.close();
  123 + // ignore: close_sinks
  124 + var socket = await response.detachSocket();
  125 + var webSocket = WebSocket.fromUpgradedSocket(
  126 + socket,
  127 + serverSide: false,
  128 + );
  129 +
  130 + return webSocket;
  131 + } on Exception catch (_) {
  132 + rethrow;
  133 + }
  134 + }
  135 +}
  1 +class BaseWebSocket {
  2 + String url;
  3 + Duration ping;
  4 + BaseWebSocket(this.url, {this.ping = const Duration(seconds: 5)}) {
  5 + throw 'To use sockets you need dart:io or dart:html';
  6 + }
  7 +
  8 + void close([int status, String reason]) {
  9 + throw 'To use sockets you need dart:io or dart:html';
  10 + }
  11 +}
@@ -221,7 +221,7 @@ class GetInstance { @@ -221,7 +221,7 @@ class GetInstance {
221 S _startController<S>({String tag}) { 221 S _startController<S>({String tag}) {
222 final key = _getKey(S, tag); 222 final key = _getKey(S, tag);
223 final i = _singl[key].getDependency() as S; 223 final i = _singl[key].getDependency() as S;
224 - if (i is GetLifeCycle) { 224 + if (i is GetLifeCycleBase) {
225 if (i.onStart != null) { 225 if (i.onStart != null) {
226 i.onStart(); 226 i.onStart();
227 Get.log('"$key" has been initialized'); 227 Get.log('"$key" has been initialized');
@@ -115,7 +115,8 @@ class GetObserver extends NavigatorObserver { @@ -115,7 +115,8 @@ class GetObserver extends NavigatorObserver {
115 value.removed = ''; 115 value.removed = '';
116 value.previous = _extractRouteName(previousRoute) ?? ''; 116 value.previous = _extractRouteName(previousRoute) ?? '';
117 value.isSnackbar = newRoute.isSnackbar ? true : value.isSnackbar ?? false; 117 value.isSnackbar = newRoute.isSnackbar ? true : value.isSnackbar ?? false;
118 - value.isBottomSheet = newRoute.isBottomSheet ? true : value.isBottomSheet ?? false; 118 + value.isBottomSheet =
  119 + newRoute.isBottomSheet ? true : value.isBottomSheet ?? false;
119 value.isDialog = newRoute.isDialog ? true : value.isDialog ?? false; 120 value.isDialog = newRoute.isDialog ? true : value.isDialog ?? false;
120 }); 121 });
121 122
@@ -154,7 +155,8 @@ class GetObserver extends NavigatorObserver { @@ -154,7 +155,8 @@ class GetObserver extends NavigatorObserver {
154 value.removed = ''; 155 value.removed = '';
155 value.previous = newRoute.name ?? ''; 156 value.previous = newRoute.name ?? '';
156 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar; 157 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
157 - value.isBottomSheet = currentRoute.isBottomSheet ? false : value.isBottomSheet; 158 + value.isBottomSheet =
  159 + currentRoute.isBottomSheet ? false : value.isBottomSheet;
158 value.isDialog = currentRoute.isDialog ? false : value.isDialog; 160 value.isDialog = currentRoute.isDialog ? false : value.isDialog;
159 }); 161 });
160 162
@@ -184,7 +186,8 @@ class GetObserver extends NavigatorObserver { @@ -184,7 +186,8 @@ class GetObserver extends NavigatorObserver {
184 value.removed = ''; 186 value.removed = '';
185 value.previous = '$oldName'; 187 value.previous = '$oldName';
186 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar; 188 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
187 - value.isBottomSheet = currentRoute.isBottomSheet ? false : value.isBottomSheet; 189 + value.isBottomSheet =
  190 + currentRoute.isBottomSheet ? false : value.isBottomSheet;
188 value.isDialog = currentRoute.isDialog ? false : value.isDialog; 191 value.isDialog = currentRoute.isDialog ? false : value.isDialog;
189 }); 192 });
190 193
@@ -205,7 +208,8 @@ class GetObserver extends NavigatorObserver { @@ -205,7 +208,8 @@ class GetObserver extends NavigatorObserver {
205 value.removed = routeName ?? ''; 208 value.removed = routeName ?? '';
206 value.previous = routeName ?? ''; 209 value.previous = routeName ?? '';
207 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar; 210 value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
208 - value.isBottomSheet = currentRoute.isBottomSheet ? false : value.isBottomSheet; 211 + value.isBottomSheet =
  212 + currentRoute.isBottomSheet ? false : value.isBottomSheet;
209 value.isDialog = currentRoute.isDialog ? false : value.isDialog; 213 value.isDialog = currentRoute.isDialog ? false : value.isDialog;
210 }); 214 });
211 215
@@ -3,7 +3,6 @@ part of rx_types; @@ -3,7 +3,6 @@ part of rx_types;
3 /// global object that registers against `GetX` and `Obx`, and allows the 3 /// global object that registers against `GetX` and `Obx`, and allows the
4 /// reactivity 4 /// reactivity
5 /// of those `Widgets` and Rx values. 5 /// of those `Widgets` and Rx values.
6 -RxInterface getObs;  
7 6
8 mixin RxObjectMixin<T> on NotifyManager<T> { 7 mixin RxObjectMixin<T> on NotifyManager<T> {
9 T _value; 8 T _value;
@@ -104,8 +103,8 @@ mixin RxObjectMixin<T> on NotifyManager<T> { @@ -104,8 +103,8 @@ mixin RxObjectMixin<T> on NotifyManager<T> {
104 103
105 /// Returns the current [value] 104 /// Returns the current [value]
106 T get value { 105 T get value {
107 - if (getObs != null) {  
108 - getObs.addListener(subject); 106 + if (RxInterface.proxy != null) {
  107 + RxInterface.proxy.addListener(subject);
109 } 108 }
110 return _value; 109 return _value;
111 } 110 }
@@ -15,6 +15,8 @@ abstract class RxInterface<T> { @@ -15,6 +15,8 @@ abstract class RxInterface<T> {
15 /// Close the Rx Variable 15 /// Close the Rx Variable
16 void close(); 16 void close();
17 17
  18 + static RxInterface proxy;
  19 +
18 /// Calls [callback] with current value, when the value changes. 20 /// Calls [callback] with current value, when the value changes.
19 StreamSubscription<T> listen(void Function(T event) onData, 21 StreamSubscription<T> listen(void Function(T event) onData,
20 {Function onError, void Function() onDone, bool cancelOnError}); 22 {Function onError, void Function() onDone, bool cancelOnError});
@@ -87,8 +87,8 @@ class RxList<E> extends ListMixin<E> @@ -87,8 +87,8 @@ class RxList<E> extends ListMixin<E>
87 @override 87 @override
88 @protected 88 @protected
89 List<E> get value { 89 List<E> get value {
90 - if (getObs != null) {  
91 - getObs.addListener(subject); 90 + if (RxInterface.proxy != null) {
  91 + RxInterface.proxy.addListener(subject);
92 } 92 }
93 return _value; 93 return _value;
94 } 94 }
@@ -39,8 +39,8 @@ class RxMap<K, V> extends MapMixin<K, V> @@ -39,8 +39,8 @@ class RxMap<K, V> extends MapMixin<K, V>
39 @override 39 @override
40 @protected 40 @protected
41 Map<K, V> get value { 41 Map<K, V> get value {
42 - if (getObs != null) {  
43 - getObs.addListener(subject); 42 + if (RxInterface.proxy != null) {
  43 + RxInterface.proxy.addListener(subject);
44 } 44 }
45 return _value; 45 return _value;
46 } 46 }
@@ -61,8 +61,8 @@ class RxSet<E> extends SetMixin<E> @@ -61,8 +61,8 @@ class RxSet<E> extends SetMixin<E>
61 @override 61 @override
62 @protected 62 @protected
63 Set<E> get value { 63 Set<E> get value {
64 - if (getObs != null) {  
65 - getObs.addListener(subject); 64 + if (RxInterface.proxy != null) {
  65 + RxInterface.proxy.addListener(subject);
66 } 66 }
67 return _value; 67 return _value;
68 } 68 }
@@ -113,8 +113,8 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { @@ -113,8 +113,8 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
113 } 113 }
114 114
115 Widget get notifyChildren { 115 Widget get notifyChildren {
116 - final observer = getObs;  
117 - getObs = _observer; 116 + final observer = RxInterface.proxy;
  117 + RxInterface.proxy = _observer;
118 final result = widget.builder(controller); 118 final result = widget.builder(controller);
119 if (!_observer.canUpdate) { 119 if (!_observer.canUpdate) {
120 throw """ 120 throw """
@@ -126,7 +126,7 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { @@ -126,7 +126,7 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
126 If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. 126 If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
127 """; 127 """;
128 } 128 }
129 - getObs = observer; 129 + RxInterface.proxy = observer;
130 return result; 130 return result;
131 } 131 }
132 132
@@ -41,8 +41,8 @@ class _ObxState extends State<ObxWidget> { @@ -41,8 +41,8 @@ class _ObxState extends State<ObxWidget> {
41 } 41 }
42 42
43 Widget get notifyChilds { 43 Widget get notifyChilds {
44 - final observer = getObs;  
45 - getObs = _observer; 44 + final observer = RxInterface.proxy;
  45 + RxInterface.proxy = _observer;
46 final result = widget.build(); 46 final result = widget.build();
47 if (!_observer.canUpdate) { 47 if (!_observer.canUpdate) {
48 throw """ 48 throw """
@@ -54,7 +54,7 @@ class _ObxState extends State<ObxWidget> { @@ -54,7 +54,7 @@ class _ObxState extends State<ObxWidget> {
54 If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. 54 If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
55 """; 55 """;
56 } 56 }
57 - getObs = observer; 57 + RxInterface.proxy = observer;
58 return result; 58 return result;
59 } 59 }
60 60
@@ -59,6 +59,12 @@ extension ContextExtensionss on BuildContext { @@ -59,6 +59,12 @@ extension ContextExtensionss on BuildContext {
59 /// similar to [MediaQuery.of(context).padding] 59 /// similar to [MediaQuery.of(context).padding]
60 ThemeData get theme => Theme.of(this); 60 ThemeData get theme => Theme.of(this);
61 61
  62 + /// Check if dark mode theme is enable
  63 + bool get isDarkMode => (theme.brightness == Brightness.dark);
  64 +
  65 + /// give access to Theme.of(context).iconTheme.color
  66 + Color get iconColor => theme.iconTheme.color;
  67 +
62 /// similar to [MediaQuery.of(context).padding] 68 /// similar to [MediaQuery.of(context).padding]
63 TextTheme get textTheme => Theme.of(this).textTheme; 69 TextTheme get textTheme => Theme.of(this).textTheme;
64 70