Jonatas

update Rx Structure from Inherited to Composition

Showing 53 changed files with 2361 additions and 1086 deletions
@@ -49,6 +49,7 @@ linter: @@ -49,6 +49,7 @@ linter:
49 prefer_equal_for_default_values: true 49 prefer_equal_for_default_values: true
50 avoid_init_to_null: true 50 avoid_init_to_null: true
51 unnecessary_getters_setters: true 51 unnecessary_getters_setters: true
  52 + annotate_overrides: true
52 #- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23 53 #- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
53 #- prefer_expression_function_bodies # consider 54 #- prefer_expression_function_bodies # consider
54 unnecessary_this: true 55 unnecessary_this: true
  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 +<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 +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 +};
  13 +
  14 +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
  15 +
  16 +// Implements GApplication::activate.
  17 +static void my_application_activate(GApplication* application) {
  18 + GtkWindow* window =
  19 + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
  20 +
  21 + // Use a header bar when running in GNOME as this is the common style used
  22 + // by applications and is the setup most users will be using (e.g. Ubuntu
  23 + // desktop).
  24 + // If running on X and not using GNOME then just use a traditional title bar
  25 + // in case the window manager does more exotic layout, e.g. tiling.
  26 + // If running on Wayland assume the header bar will work (may need changing
  27 + // if future cases occur).
  28 + gboolean use_header_bar = TRUE;
  29 +#ifdef GDK_WINDOWING_X11
  30 + GdkScreen *screen = gtk_window_get_screen(window);
  31 + if (GDK_IS_X11_SCREEN(screen)) {
  32 + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
  33 + if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
  34 + use_header_bar = FALSE;
  35 + }
  36 + }
  37 +#endif
  38 + if (use_header_bar) {
  39 + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
  40 + gtk_widget_show(GTK_WIDGET(header_bar));
  41 + gtk_header_bar_set_title(header_bar, "example");
  42 + gtk_header_bar_set_show_close_button(header_bar, TRUE);
  43 + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
  44 + }
  45 + else {
  46 + gtk_window_set_title(window, "example");
  47 + }
  48 +
  49 + gtk_window_set_default_size(window, 1280, 720);
  50 + gtk_widget_show(GTK_WIDGET(window));
  51 +
  52 + g_autoptr(FlDartProject) project = fl_dart_project_new();
  53 +
  54 + FlView* view = fl_view_new(project);
  55 + gtk_widget_show(GTK_WIDGET(view));
  56 + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
  57 +
  58 + fl_register_plugins(FL_PLUGIN_REGISTRY(view));
  59 +
  60 + gtk_widget_grab_focus(GTK_WIDGET(view));
  61 +}
  62 +
  63 +static void my_application_class_init(MyApplicationClass* klass) {
  64 + G_APPLICATION_CLASS(klass)->activate = my_application_activate;
  65 +}
  66 +
  67 +static void my_application_init(MyApplication* self) {}
  68 +
  69 +MyApplication* my_application_new() {
  70 + return MY_APPLICATION(g_object_new(my_application_get_type(),
  71 + "application-id", APPLICATION_ID,
  72 + nullptr));
  73 +}
  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_
  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 +}
@@ -11,9 +11,6 @@ import 'root/parse_route.dart'; @@ -11,9 +11,6 @@ import 'root/parse_route.dart';
11 import 'root/root_controller.dart'; 11 import 'root/root_controller.dart';
12 import 'routes/transitions_type.dart'; 12 import 'routes/transitions_type.dart';
13 13
14 -//TODO: Split this class on "Snackbar" "Dialog" "bottomSheet"  
15 -//and "navigation" extensions  
16 -  
17 extension ExtensionSnackbar on GetInterface { 14 extension ExtensionSnackbar on GetInterface {
18 void rawSnackbar({ 15 void rawSnackbar({
19 String title, 16 String title,
1 library get_rx; 1 library get_rx;
2 2
3 -export 'src/rx_core/rx_impl.dart';  
4 -export 'src/rx_core/rx_interface.dart';  
5 -export 'src/rx_iterables/rx_list.dart';  
6 -export 'src/rx_iterables/rx_map.dart';  
7 -export 'src/rx_iterables/rx_set.dart'; 3 +export 'src/rx_stream/rx_stream.dart';
  4 +export 'src/rx_types/rx_types.dart';
8 export 'src/rx_workers/rx_workers.dart'; 5 export 'src/rx_workers/rx_workers.dart';
1 -import 'dart:async';  
2 -import 'dart:collection';  
3 -import 'dart:math';  
4 -import 'package:flutter/foundation.dart';  
5 -  
6 -import '../rx_core/rx_impl.dart';  
7 -import '../rx_core/rx_interface.dart';  
8 -import '../rx_typedefs/rx_typedefs.dart';  
9 -  
10 -/// Create a list similar to `List<T>`  
11 -class RxList<E> implements List<E>, RxInterface<List<E>> {  
12 - RxList([List<E> initial]) {  
13 - if (initial != null) _list = initial;  
14 - }  
15 -  
16 - List<E> _list = <E>[];  
17 -  
18 - @override  
19 - Iterator<E> get iterator => value.iterator;  
20 -  
21 - @override  
22 - bool get isEmpty => value.isEmpty;  
23 -  
24 - bool get canUpdate {  
25 - return _subscriptions.length > 0;  
26 - }  
27 -  
28 - @override  
29 - bool get isNotEmpty => value.isNotEmpty;  
30 -  
31 - @override  
32 - StreamController<List<E>> subject = StreamController.broadcast();  
33 -  
34 - final _subscriptions = HashMap<Stream<List<E>>, StreamSubscription>();  
35 -  
36 - void operator []=(int index, E val) {  
37 - _list[index] = val;  
38 - refresh();  
39 - }  
40 -  
41 - void refresh() {  
42 - subject.add(_list);  
43 - }  
44 -  
45 - /// Special override to push() element(s) in a reactive way  
46 - /// inside the List,  
47 - RxList<E> operator +(Iterable<E> val) {  
48 - addAll(val);  
49 - refresh();  
50 - return this;  
51 - }  
52 -  
53 - E operator [](int index) {  
54 - return value[index];  
55 - }  
56 -  
57 - void add(E item) {  
58 - _list.add(item);  
59 - refresh();  
60 - }  
61 -  
62 - @override  
63 - void addAll(Iterable<E> item) {  
64 - _list.addAll(item);  
65 - refresh();  
66 - }  
67 -  
68 - /// Add [item] to [List<E>] only if [item] is not null.  
69 - void addNonNull(E item) {  
70 - if (item != null) add(item);  
71 - }  
72 -  
73 - /// Add [Iterable<E>] to [List<E>] only if [Iterable<E>] is not null.  
74 - void addAllNonNull(Iterable<E> item) {  
75 - if (item != null) addAll(item);  
76 - }  
77 -  
78 - /// Add [item] to [List<E>] only if [condition] is true.  
79 - void addIf(dynamic condition, E item) {  
80 - if (condition is Condition) condition = condition();  
81 - if (condition is bool && condition) add(item);  
82 - }  
83 -  
84 - /// Adds [Iterable<E>] to [List<E>] only if [condition] is true.  
85 - void addAllIf(dynamic condition, Iterable<E> items) {  
86 - if (condition is Condition) condition = condition();  
87 - if (condition is bool && condition) addAll(items);  
88 - }  
89 -  
90 - @override  
91 - void insert(int index, E item) {  
92 - _list.insert(index, item);  
93 - refresh();  
94 - }  
95 -  
96 - @override  
97 - void insertAll(int index, Iterable<E> iterable) {  
98 - _list.insertAll(index, iterable);  
99 - refresh();  
100 - }  
101 -  
102 - @override  
103 - int get length => value.length;  
104 -  
105 - /// Removes an item from the list.  
106 - ///  
107 - /// This is O(N) in the number of items in the list.  
108 - ///  
109 - /// Returns whether the item was present in the list.  
110 - @override  
111 - bool remove(Object item) {  
112 - final hasRemoved = _list.remove(item);  
113 - if (hasRemoved) {  
114 - refresh();  
115 - }  
116 - return hasRemoved;  
117 - }  
118 -  
119 - @override  
120 - E removeAt(int index) {  
121 - final item = _list.removeAt(index);  
122 - refresh();  
123 - return item;  
124 - }  
125 -  
126 - @override  
127 - E removeLast() {  
128 - final item = _list.removeLast();  
129 - refresh();  
130 - return item;  
131 - }  
132 -  
133 - @override  
134 - void removeRange(int start, int end) {  
135 - _list.removeRange(start, end);  
136 - refresh();  
137 - }  
138 -  
139 - @override  
140 - void removeWhere(bool Function(E) test) {  
141 - _list.removeWhere(test);  
142 - refresh();  
143 - }  
144 -  
145 - @override  
146 - void clear() {  
147 - _list.clear();  
148 - refresh();  
149 - }  
150 -  
151 - @override  
152 - void sort([int compare(E a, E b)]) {  
153 - _list.sort(compare);  
154 - refresh();  
155 - }  
156 -  
157 - @override  
158 - void close() {  
159 - _subscriptions.forEach((observable, subscription) {  
160 - subscription.cancel();  
161 - });  
162 - _subscriptions.clear();  
163 - subject.close();  
164 - }  
165 -  
166 - /// Replaces all existing items of this list with [item]  
167 - void assign(E item) {  
168 - clear();  
169 - add(item);  
170 - }  
171 -  
172 - void update(void fn(Iterable<E> value)) {  
173 - fn(value);  
174 - refresh();  
175 - }  
176 -  
177 - /// Replaces all existing items of this list with [items]  
178 - void assignAll(Iterable<E> items) {  
179 - clear();  
180 - addAll(items);  
181 - }  
182 -  
183 - @protected  
184 - List<E> get value {  
185 - if (getObs != null) {  
186 - getObs.addListener(subject.stream);  
187 - }  
188 - return _list;  
189 - }  
190 -  
191 - String get string => value.toString();  
192 -  
193 - void addListener(Stream<List<E>> rxGetX) {  
194 - if (_subscriptions.containsKey(rxGetX)) {  
195 - return;  
196 - }  
197 - _subscriptions[rxGetX] = rxGetX.listen(subject.add);  
198 - }  
199 -  
200 - set value(List<E> val) {  
201 - if (_list == val) return;  
202 - _list = val;  
203 - refresh();  
204 - }  
205 -  
206 - Stream<List<E>> get stream => subject.stream;  
207 -  
208 - StreamSubscription<List<E>> listen(  
209 - void Function(List<E>) onData, {  
210 - Function onError,  
211 - void Function() onDone,  
212 - bool cancelOnError,  
213 - }) =>  
214 - stream.listen(onData, onError: onError, onDone: onDone);  
215 -  
216 - /// Binds an existing [Stream<List>] to this [RxList].  
217 - /// You can bind multiple sources to update the value.  
218 - /// Closing the subscription will happen automatically when the observer  
219 - /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.  
220 - void bindStream(Stream<List<E>> stream) {  
221 - _subscriptions[stream] = stream.listen((va) => value = va);  
222 - }  
223 -  
224 - @override  
225 - E get first => value.first;  
226 -  
227 - @override  
228 - E get last => value.last;  
229 -  
230 - @override  
231 - bool any(bool Function(E) test) {  
232 - return value.any(test);  
233 - }  
234 -  
235 - @override  
236 - Map<int, E> asMap() {  
237 - return value.asMap();  
238 - }  
239 -  
240 - @override  
241 - List<R> cast<R>() {  
242 - return value.cast<R>();  
243 - }  
244 -  
245 - @override  
246 - bool contains(Object element) {  
247 - return value.contains(element);  
248 - }  
249 -  
250 - @override  
251 - E elementAt(int index) {  
252 - return value.elementAt(index);  
253 - }  
254 -  
255 - @override  
256 - bool every(bool Function(E) test) {  
257 - return value.every(test);  
258 - }  
259 -  
260 - @override  
261 - Iterable<T> expand<T>(Iterable<T> Function(E) f) {  
262 - return value.expand(f);  
263 - }  
264 -  
265 - @override  
266 - void fillRange(int start, int end, [E fillValue]) {  
267 - _list.fillRange(start, end, fillValue);  
268 - refresh();  
269 - }  
270 -  
271 - @override  
272 - E firstWhere(bool Function(E) test, {E Function() orElse}) {  
273 - return value.firstWhere(test, orElse: orElse);  
274 - }  
275 -  
276 - @override  
277 - T fold<T>(T initialValue, T Function(T, E) combine) {  
278 - return value.fold(initialValue, combine);  
279 - }  
280 -  
281 - @override  
282 - Iterable<E> followedBy(Iterable<E> other) {  
283 - return value.followedBy(other);  
284 - }  
285 -  
286 - @override  
287 - void forEach(void Function(E) f) {  
288 - value.forEach(f);  
289 - }  
290 -  
291 - @override  
292 - Iterable<E> getRange(int start, int end) {  
293 - return value.getRange(start, end);  
294 - }  
295 -  
296 - @override  
297 - int indexOf(E element, [int start = 0]) {  
298 - return value.indexOf(element, start);  
299 - }  
300 -  
301 - @override  
302 - int indexWhere(bool Function(E) test, [int start = 0]) {  
303 - return value.indexWhere(test, start);  
304 - }  
305 -  
306 - @override  
307 - String join([String separator = ""]) {  
308 - return value.join(separator);  
309 - }  
310 -  
311 - @override  
312 - int lastIndexOf(E element, [int start]) {  
313 - return value.lastIndexOf(element, start);  
314 - }  
315 -  
316 - @override  
317 - int lastIndexWhere(bool Function(E) test, [int start]) {  
318 - return value.lastIndexWhere(test, start);  
319 - }  
320 -  
321 - @override  
322 - E lastWhere(bool Function(E) test, {E Function() orElse}) {  
323 - return value.lastWhere(test, orElse: orElse);  
324 - }  
325 -  
326 - @override  
327 - set length(int newLength) {  
328 - _list.length = newLength;  
329 - refresh();  
330 - }  
331 -  
332 - @override  
333 - Iterable<T> map<T>(T Function(E) f) {  
334 - return value.map(f);  
335 - }  
336 -  
337 - @override  
338 - E reduce(E Function(E, E) combine) {  
339 - return value.reduce(combine);  
340 - }  
341 -  
342 - @override  
343 - void replaceRange(int start, int end, Iterable<E> replacement) {  
344 - _list.replaceRange(start, end, replacement);  
345 - refresh();  
346 - }  
347 -  
348 - @override  
349 - void retainWhere(bool Function(E) test) {  
350 - _list.retainWhere(test);  
351 - refresh();  
352 - }  
353 -  
354 - @override  
355 - Iterable<E> get reversed => value.reversed;  
356 -  
357 - @override  
358 - void setAll(int index, Iterable<E> iterable) {  
359 - _list.setAll(index, iterable);  
360 - refresh();  
361 - }  
362 -  
363 - @override  
364 - void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {  
365 - _list.setRange(start, end, iterable, skipCount);  
366 - refresh();  
367 - }  
368 -  
369 - @override  
370 - void shuffle([Random random]) {  
371 - _list.shuffle(random);  
372 - refresh();  
373 - }  
374 -  
375 - @override  
376 - E get single => value.single;  
377 -  
378 - @override  
379 - E singleWhere(bool Function(E) test, {E Function() orElse}) {  
380 - return value.singleWhere(test, orElse: orElse);  
381 - }  
382 -  
383 - @override  
384 - Iterable<E> skip(int count) {  
385 - return value.skip(count);  
386 - }  
387 -  
388 - @override  
389 - Iterable<E> skipWhile(bool Function(E) test) {  
390 - return value.skipWhile(test);  
391 - }  
392 -  
393 - @override  
394 - List<E> sublist(int start, [int end]) {  
395 - return value.sublist(start, end);  
396 - }  
397 -  
398 - @override  
399 - Iterable<E> take(int count) {  
400 - return value.take(count);  
401 - }  
402 -  
403 - @override  
404 - Iterable<E> takeWhile(bool Function(E) test) {  
405 - return value.takeWhile(test);  
406 - }  
407 -  
408 - @override  
409 - List<E> toList({bool growable = true}) {  
410 - return value.toList(growable: growable);  
411 - }  
412 -  
413 - @override  
414 - Set<E> toSet() {  
415 - return value.toSet();  
416 - }  
417 -  
418 - @override  
419 - Iterable<E> where(bool Function(E) test) {  
420 - return value.where(test);  
421 - }  
422 -  
423 - @override  
424 - Iterable<T> whereType<T>() {  
425 - return value.whereType<T>();  
426 - }  
427 -  
428 - @override  
429 - set first(E value) {  
430 - _list.first = value;  
431 - refresh();  
432 - }  
433 -  
434 - @override  
435 - set last(E value) {  
436 - _list.last = value;  
437 - refresh();  
438 - }  
439 -}  
440 -  
441 -extension ListExtension<E> on List<E> {  
442 - RxList<E> get obs {  
443 - if (this != null) {  
444 - return RxList<E>(<E>[])..addAllNonNull(this);  
445 - } else {  
446 - return RxList<E>(null);  
447 - }  
448 - }  
449 -}  
1 -import 'dart:async';  
2 -import 'dart:collection';  
3 -import 'package:flutter/foundation.dart';  
4 -  
5 -import '../rx_core/rx_impl.dart';  
6 -import '../rx_core/rx_interface.dart';  
7 -import '../rx_typedefs/rx_typedefs.dart';  
8 -  
9 -class RxSet<E> implements Set<E>, RxInterface<Set<E>> {  
10 - RxSet([Set<E> initial]) {  
11 - if (initial != null) _set = initial;  
12 - }  
13 -  
14 - Set<E> _set = <E>{};  
15 -  
16 - @override  
17 - Iterator<E> get iterator => value.iterator;  
18 -  
19 - @override  
20 - bool get isEmpty => value.isEmpty;  
21 -  
22 - bool get canUpdate {  
23 - return _subscriptions.length > 0;  
24 - }  
25 -  
26 - @override  
27 - bool get isNotEmpty => value.isNotEmpty;  
28 -  
29 - StreamController<Set<E>> subject = StreamController<Set<E>>.broadcast();  
30 - final _subscriptions = HashMap<Stream<Set<E>>, StreamSubscription>();  
31 -  
32 - /// Adds [item] only if [condition] resolves to true.  
33 - void addIf(dynamic condition, E item) {  
34 - if (condition is Condition) condition = condition();  
35 - if (condition is bool && condition) add(item);  
36 - }  
37 -  
38 - /// Adds all [items] only if [condition] resolves to true.  
39 - void addAllIf(dynamic condition, Iterable<E> items) {  
40 - if (condition is Condition) condition = condition();  
41 - if (condition is bool && condition) addAll(items);  
42 - }  
43 -  
44 - void refresh() {  
45 - subject.add(_set);  
46 - }  
47 -  
48 - /// Special override to push() element(s) in a reactive way  
49 - /// inside the List,  
50 - RxSet<E> operator +(Set<E> val) {  
51 - addAll(val);  
52 - refresh();  
53 - return this;  
54 - }  
55 -  
56 - @override  
57 - bool add(E value) {  
58 - final val = _set.add(value);  
59 - refresh();  
60 - return val;  
61 - }  
62 -  
63 - @override  
64 - void addAll(Iterable<E> item) {  
65 - _set.addAll(item);  
66 - refresh();  
67 - }  
68 -  
69 - /// Adds only if [item] is not null.  
70 - void addNonNull(E item) {  
71 - if (item != null) add(item);  
72 - }  
73 -  
74 - /// Adds only if [item] is not null.  
75 - void addAllNonNull(Iterable<E> item) {  
76 - if (item != null) addAll(item);  
77 - }  
78 -  
79 - int get length => value.length;  
80 -  
81 - /// Removes an item from the list.  
82 - ///  
83 - /// This is O(N) in the number of items in the list.  
84 - ///  
85 - /// Returns whether the item was present in the list.  
86 - bool remove(Object item) {  
87 - var hasRemoved = _set.remove(item);  
88 - if (hasRemoved) {  
89 - refresh();  
90 - }  
91 - return hasRemoved;  
92 - }  
93 -  
94 - void removeWhere(bool Function(E) test) {  
95 - _set.removeWhere(test);  
96 - refresh();  
97 - }  
98 -  
99 - void clear() {  
100 - _set.clear();  
101 - refresh();  
102 - }  
103 -  
104 - void close() {  
105 - _subscriptions.forEach((observable, subscription) {  
106 - subscription.cancel();  
107 - });  
108 - _subscriptions.clear();  
109 - subject.close();  
110 - }  
111 -  
112 - /// Replaces all existing items of this list with [item]  
113 - void assign(E item) {  
114 - clear();  
115 - add(item);  
116 - }  
117 -  
118 - void update(void fn(Iterable<E> value)) {  
119 - fn(value);  
120 - refresh();  
121 - }  
122 -  
123 - /// Replaces all existing items of this list with [items]  
124 - void assignAll(Iterable<E> items) {  
125 - clear();  
126 - addAll(items);  
127 - }  
128 -  
129 - @protected  
130 - Set<E> get value {  
131 - if (getObs != null) {  
132 - getObs.addListener(subject.stream);  
133 - }  
134 - return _set;  
135 - }  
136 -  
137 - String get string => value.toString();  
138 -  
139 - void addListener(Stream<Set<E>> rxGetX) {  
140 - if (_subscriptions.containsKey(rxGetX)) {  
141 - return;  
142 - }  
143 - _subscriptions[rxGetX] = rxGetX.listen((data) {  
144 - subject.add(data);  
145 - });  
146 - }  
147 -  
148 - set value(Set<E> val) {  
149 - if (_set == val) return;  
150 - _set = val;  
151 - refresh();  
152 - }  
153 -  
154 - Stream<Set<E>> get stream => subject.stream;  
155 -  
156 - StreamSubscription<Set<E>> listen(void Function(Set<E>) onData,  
157 - {Function onError, void Function() onDone, bool cancelOnError}) =>  
158 - stream.listen(onData, onError: onError, onDone: onDone);  
159 -  
160 - /// Binds an existing [Stream<Set>] to this [RxSet].  
161 - /// You can bind multiple sources to update the value.  
162 - /// Closing the subscription will happen automatically when the observer  
163 - /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.  
164 - void bindStream(Stream<Set<E>> stream) {  
165 - _subscriptions[stream] = stream.listen((va) => value = va);  
166 - }  
167 -  
168 - @override  
169 - E get first => value.first;  
170 -  
171 - @override  
172 - E get last => value.last;  
173 -  
174 - @override  
175 - bool any(bool Function(E) test) {  
176 - return value.any(test);  
177 - }  
178 -  
179 - @override  
180 - Set<R> cast<R>() {  
181 - return value.cast<R>();  
182 - }  
183 -  
184 - @override  
185 - bool contains(Object element) {  
186 - return value.contains(element);  
187 - }  
188 -  
189 - @override  
190 - E elementAt(int index) {  
191 - return value.elementAt(index);  
192 - }  
193 -  
194 - @override  
195 - bool every(bool Function(E) test) {  
196 - return value.every(test);  
197 - }  
198 -  
199 - @override  
200 - Iterable<T> expand<T>(Iterable<T> Function(E) f) {  
201 - return value.expand(f);  
202 - }  
203 -  
204 - @override  
205 - E firstWhere(bool Function(E) test, {E Function() orElse}) {  
206 - return value.firstWhere(test, orElse: orElse);  
207 - }  
208 -  
209 - @override  
210 - T fold<T>(T initialValue, T Function(T, E) combine) {  
211 - return value.fold(initialValue, combine);  
212 - }  
213 -  
214 - @override  
215 - Iterable<E> followedBy(Iterable<E> other) {  
216 - return value.followedBy(other);  
217 - }  
218 -  
219 - @override  
220 - void forEach(void Function(E) f) {  
221 - value.forEach(f);  
222 - }  
223 -  
224 - @override  
225 - String join([String separator = ""]) {  
226 - return value.join(separator);  
227 - }  
228 -  
229 - @override  
230 - E lastWhere(bool Function(E) test, {E Function() orElse}) {  
231 - return value.lastWhere(test, orElse: orElse);  
232 - }  
233 -  
234 - @override  
235 - Iterable<T> map<T>(T Function(E) f) {  
236 - return value.map(f);  
237 - }  
238 -  
239 - @override  
240 - E reduce(E Function(E, E) combine) {  
241 - return value.reduce(combine);  
242 - }  
243 -  
244 - @override  
245 - E get single => value.single;  
246 -  
247 - @override  
248 - E singleWhere(bool Function(E) test, {E Function() orElse}) {  
249 - return value.singleWhere(test, orElse: orElse);  
250 - }  
251 -  
252 - @override  
253 - Iterable<E> skip(int count) {  
254 - return value.skip(count);  
255 - }  
256 -  
257 - @override  
258 - Iterable<E> skipWhile(bool Function(E) test) {  
259 - return value.skipWhile(test);  
260 - }  
261 -  
262 - @override  
263 - Iterable<E> take(int count) {  
264 - return value.take(count);  
265 - }  
266 -  
267 - @override  
268 - Iterable<E> takeWhile(bool Function(E) test) {  
269 - return value.takeWhile(test);  
270 - }  
271 -  
272 - @override  
273 - List<E> toList({bool growable = true}) {  
274 - return value.toList(growable: growable);  
275 - }  
276 -  
277 - @override  
278 - Set<E> toSet() {  
279 - return value.toSet();  
280 - }  
281 -  
282 - @override  
283 - Iterable<E> where(bool Function(E) test) {  
284 - return value.where(test);  
285 - }  
286 -  
287 - @override  
288 - Iterable<T> whereType<T>() {  
289 - return value.whereType<T>();  
290 - }  
291 -  
292 - @override  
293 - bool containsAll(Iterable<Object> other) {  
294 - return value.containsAll(other);  
295 - }  
296 -  
297 - @override  
298 - Set<E> difference(Set<Object> other) {  
299 - return value.difference(other);  
300 - }  
301 -  
302 - @override  
303 - Set<E> intersection(Set<Object> other) {  
304 - return value.intersection(other);  
305 - }  
306 -  
307 - @override  
308 - E lookup(Object object) {  
309 - return value.lookup(object);  
310 - }  
311 -  
312 - @override  
313 - void removeAll(Iterable<Object> elements) {  
314 - _set.removeAll(elements);  
315 - refresh();  
316 - }  
317 -  
318 - @override  
319 - void retainAll(Iterable<Object> elements) {  
320 - _set.retainAll(elements);  
321 - refresh();  
322 - }  
323 -  
324 - @override  
325 - void retainWhere(bool Function(E) E) {  
326 - _set.retainWhere(E);  
327 - refresh();  
328 - }  
329 -  
330 - @override  
331 - Set<E> union(Set<E> other) {  
332 - return value.union(other);  
333 - }  
334 -}  
335 -  
336 -extension SetExtension<E> on Set<E> {  
337 - RxSet<E> get obs {  
338 - if (this != null) {  
339 - return RxSet<E>(<E>{})..addAllNonNull(this);  
340 - } else {  
341 - return RxSet<E>(null);  
342 - }  
343 - }  
344 -}  
  1 +part of rx_stream;
  2 +
  3 +/// [GetStream] is the lightest and most performative way of working
  4 +/// with events at Dart. You sintaxe is like StreamController, but it works
  5 +/// with simple callbacks. In this way, every event calls only one function.
  6 +/// There is no buffering, to very low memory consumption.
  7 +/// event [add] will add a object to stream. [addError] will add a error
  8 +/// to stream. [listen] is a very light StreamSubscription interface.
  9 +/// Is possible take the last value with [value] property.
  10 +class GetStream<T> {
  11 + LightListenable<T> listenable = LightListenable<T>();
  12 +
  13 + T _value;
  14 +
  15 + T get value => _value;
  16 +
  17 + void add(T event) {
  18 + _value = event;
  19 + _checkIfDisposed();
  20 + listenable.notifyData(event);
  21 + }
  22 +
  23 + void _checkIfDisposed([bool isClosed = false]) {
  24 + if (listenable == null) {
  25 + throw '''[LightStream] Error:
  26 +You cannot ${isClosed ? "close" : "add events to"} a closed stream.''';
  27 + }
  28 + }
  29 +
  30 + void addError(Object error, [StackTrace stackTrace]) {
  31 + _checkIfDisposed();
  32 + listenable.notifyError(error, stackTrace);
  33 + }
  34 +
  35 + void close() {
  36 + _checkIfDisposed(true);
  37 + listenable.notifyDone();
  38 + listenable.dispose();
  39 + listenable = null;
  40 + _value = null;
  41 + }
  42 +
  43 + int get length => listenable.length;
  44 +
  45 + bool get hasListeners => listenable.hasListeners;
  46 +
  47 + bool get isClosed => listenable == null;
  48 +
  49 + LightSubscription<T> listen(void Function(T event) onData,
  50 + {Function onError, void Function() onDone, bool cancelOnError}) {
  51 + final subs = LightSubscription<T>(listenable)
  52 + ..onData(onData)
  53 + ..onError(onError)
  54 + ..onDone(onDone);
  55 + listenable.addSubscription(subs);
  56 + return subs;
  57 + }
  58 +}
  59 +
  60 +class LightListenable<T> {
  61 + List<LightSubscription<T>> _onData = <LightSubscription<T>>[];
  62 +
  63 + void removeSubscription(LightSubscription<T> subs) {
  64 + _onData.remove(subs);
  65 + }
  66 +
  67 + void addSubscription(LightSubscription<T> subs) {
  68 + _onData.add(subs);
  69 + }
  70 +
  71 + int get length => _onData?.length;
  72 +
  73 + bool get hasListeners => _onData.isNotEmpty;
  74 +
  75 + void notifyData(T data) {
  76 + _checkIfDisposed();
  77 + for (final item in _onData) {
  78 + if (item.isPaused) {
  79 + break;
  80 + }
  81 + item._data?.call(data);
  82 + }
  83 + }
  84 +
  85 + void _checkIfDisposed() {
  86 + if (isDisposed) {
  87 + throw '[LightStream] Error: You cannot add events to a closed stream.';
  88 + }
  89 + }
  90 +
  91 + void notifyError(Object error, [StackTrace stackTrace]) {
  92 + _checkIfDisposed();
  93 + for (final item in _onData) {
  94 + if (item.isPaused) {
  95 + break;
  96 + }
  97 + item._onError?.call(error, stackTrace);
  98 + if (item.cancelOnError) {
  99 + item.cancel?.call();
  100 + item._onDone?.call();
  101 + }
  102 + }
  103 + }
  104 +
  105 + void notifyDone() {
  106 + _checkIfDisposed();
  107 + for (final item in _onData) {
  108 + if (item.isPaused) {
  109 + break;
  110 + }
  111 + item._onDone?.call();
  112 + }
  113 + }
  114 +
  115 + void dispose() => _onData = null;
  116 +
  117 + bool get isDisposed => _onData == null;
  118 +}
  119 +
  120 +class LightSubscription<T> extends StreamSubscription<T> {
  121 + final LightListenable<T> listener;
  122 +
  123 + LightSubscription(this.listener);
  124 +
  125 + bool cancelOnError = false;
  126 +
  127 + @override
  128 + Future<void> cancel() async => listener.removeSubscription(this);
  129 +
  130 + OnData<T> _data;
  131 +
  132 + Function _onError;
  133 +
  134 + Callback _onDone;
  135 +
  136 + bool _isPaused = false;
  137 +
  138 + @override
  139 + void onData(OnData<T> handleData) => _data = handleData;
  140 +
  141 + @override
  142 + void onError(Function handleError) => _onError = handleError;
  143 +
  144 + @override
  145 + void onDone(Callback handleDone) => _onDone = handleDone;
  146 +
  147 + @override
  148 + void pause([Future<void> resumeSignal]) => _isPaused = true;
  149 +
  150 + @override
  151 + void resume() => _isPaused = false;
  152 +
  153 + @override
  154 + bool get isPaused => _isPaused;
  155 +
  156 + @override
  157 + Future<E> asFuture<E>([E futureValue]) => Future.value(futureValue);
  158 +}
  159 +
  160 +class GetStreamTransformation<T> extends Stream<T> {
  161 + final LightListenable<T> listenable;
  162 +
  163 + GetStreamTransformation(this.listenable);
  164 +
  165 + @override
  166 + LightSubscription<T> listen(void Function(T event) onData,
  167 + {Function onError, void Function() onDone, bool cancelOnError}) {
  168 + final subs = LightSubscription<T>(listenable)
  169 + ..onData(onData)
  170 + ..onError(onError)
  171 + ..onDone(onDone);
  172 + listenable.addSubscription(subs);
  173 + return subs;
  174 + }
  175 +}
  1 +part of rx_stream;
  2 +
  3 +class Node<T> {
  4 + T data;
  5 + Node<T> next;
  6 + Node({this.data, this.next});
  7 +}
  8 +
  9 +class MiniSubscription<T> {
  10 + const MiniSubscription(
  11 + this.data, this.onError, this.onDone, this.cancelOnError, this.listener);
  12 + final OnData<T> data;
  13 + final Function onError;
  14 + final Callback onDone;
  15 + final bool cancelOnError;
  16 +
  17 + Future<void> cancel() async => listener.removeListener(this);
  18 +
  19 + final FastList<T> listener;
  20 +}
  21 +
  22 +class MiniStream<T> {
  23 + FastList<T> listenable = FastList<T>();
  24 +
  25 + T _value;
  26 +
  27 + T get value => _value;
  28 +
  29 + set value(T val) {
  30 + add(val);
  31 + }
  32 +
  33 + void add(T event) {
  34 + assert(listenable != null);
  35 + _value = event;
  36 + listenable._notifyData(event);
  37 + }
  38 +
  39 + void addError(Object error, [StackTrace stackTrace]) {
  40 + assert(listenable != null);
  41 + listenable._notifyError(error, stackTrace);
  42 + }
  43 +
  44 + int get length => listenable.length;
  45 +
  46 + bool get hasListeners => listenable.isNotEmpty;
  47 +
  48 + bool get isClosed => listenable == null;
  49 +
  50 + MiniSubscription<T> listen(void Function(T event) onData,
  51 + {Function onError, void Function() onDone, bool cancelOnError = false}) {
  52 + final subs = MiniSubscription<T>(
  53 + onData,
  54 + onError,
  55 + onDone,
  56 + cancelOnError,
  57 + listenable,
  58 + );
  59 + listenable.addListener(subs);
  60 + return subs;
  61 + }
  62 +
  63 + void close() {
  64 + if (listenable == null) {
  65 + throw 'You can not close a closed Stream';
  66 + }
  67 + listenable._notifyDone();
  68 + listenable = null;
  69 + _value = null;
  70 + }
  71 +}
  72 +
  73 +class FastList<T> {
  74 + Node<MiniSubscription<T>> _head;
  75 +
  76 + void _notifyData(T data) {
  77 + var currentNode = _head;
  78 + do {
  79 + currentNode.data.data(data);
  80 + currentNode = currentNode.next;
  81 + } while (currentNode != null);
  82 + }
  83 +
  84 + void _notifyDone() {
  85 + var currentNode = _head;
  86 + do {
  87 + currentNode.data.onDone?.call();
  88 + currentNode = currentNode.next;
  89 + } while (currentNode != null);
  90 + }
  91 +
  92 + void _notifyError(Object error, [StackTrace stackTrace]) {
  93 + var currentNode = _head;
  94 + while (currentNode != null) {
  95 + currentNode.data.onError?.call(error, stackTrace);
  96 + currentNode = currentNode.next;
  97 + }
  98 + }
  99 +
  100 + /// Checks if this list is empty
  101 + bool get isEmpty => _head == null;
  102 +
  103 + bool get isNotEmpty => !isEmpty;
  104 +
  105 + /// Returns the length of this list
  106 + int get length {
  107 + var length = 0;
  108 + var currentNode = _head;
  109 +
  110 + while (currentNode != null) {
  111 + currentNode = currentNode.next;
  112 + length++;
  113 + }
  114 + return length;
  115 + }
  116 +
  117 + /// Shows the element at position [position]. `null` for invalid positions.
  118 + MiniSubscription<T> _elementAt(int position) {
  119 + if (isEmpty || length < position || position < 0) return null;
  120 +
  121 + var node = _head;
  122 + var current = 0;
  123 +
  124 + while (current != position) {
  125 + node = node.next;
  126 + current++;
  127 + }
  128 + return node.data;
  129 + }
  130 +
  131 + /// Inserts [data] at the end of the list.
  132 + void addListener(MiniSubscription<T> data) {
  133 + var newNode = Node(data: data);
  134 +
  135 + if (isEmpty) {
  136 + _head = newNode;
  137 + } else {
  138 + var currentNode = _head;
  139 + while (currentNode.next != null) {
  140 + currentNode = currentNode.next;
  141 + }
  142 + currentNode.next = newNode;
  143 + }
  144 + }
  145 +
  146 + bool contains(T element) {
  147 + var length = this.length;
  148 + for (var i = 0; i < length; i++) {
  149 + if (_elementAt(i) == element) return true;
  150 + if (length != this.length) {
  151 + throw ConcurrentModificationError(this);
  152 + }
  153 + }
  154 + return false;
  155 + }
  156 +
  157 + void removeListener(MiniSubscription<T> element) {
  158 + var length = this.length;
  159 + for (var i = 0; i < length; i++) {
  160 + if (_elementAt(i) == element) {
  161 + _removeAt(i);
  162 + break;
  163 + }
  164 + }
  165 + }
  166 +
  167 + MiniSubscription<T> _removeAt(int position) {
  168 + var index = 0;
  169 + var currentNode = _head;
  170 + Node<MiniSubscription<T>> previousNode;
  171 +
  172 + if (isEmpty || length < position || position < 0) {
  173 + throw Exception('Invalid position');
  174 + } else if (position == 0) {
  175 + _head = _head.next;
  176 + } else {
  177 + while (index != position) {
  178 + previousNode = currentNode;
  179 + currentNode = currentNode.next;
  180 + index++;
  181 + }
  182 +
  183 + if (previousNode == null) {
  184 + _head = null;
  185 + } else {
  186 + previousNode.next = currentNode.next;
  187 + }
  188 +
  189 + currentNode.next = null;
  190 + }
  191 +
  192 + return currentNode.data;
  193 + }
  194 +}
  1 +library rx_stream;
  2 +
  3 +import 'dart:async';
  4 +import '../rx_typedefs/rx_typedefs.dart';
  5 +
  6 +part 'get_stream.dart';
  7 +part 'mini_stream.dart';
1 typedef Condition = bool Function(); 1 typedef Condition = bool Function();
2 -typedef ValueCallback<T> = Function(T v); 2 +typedef OnData<T> = void Function(T data);
  3 +typedef Callback = void Function();
1 -import 'dart:async';  
2 -import 'dart:collection';  
3 -import '../rx_core/rx_interface.dart';  
4 -part 'rx_num.dart'; 1 +part of rx_types;
5 2
6 /// global object that registers against `GetX` and `Obx`, and allows the 3 /// global object that registers against `GetX` and `Obx`, and allows the
7 /// reactivity 4 /// reactivity
8 /// of those `Widgets` and Rx values. 5 /// of those `Widgets` and Rx values.
9 RxInterface getObs; 6 RxInterface getObs;
10 7
11 -/// Base Rx class that manages all the stream logic for any Type.  
12 -abstract class _RxImpl<T> implements RxInterface<T> {  
13 - _RxImpl(T initial) {  
14 - _value = initial;  
15 - }  
16 - StreamController<T> subject = StreamController<T>.broadcast();  
17 - final _subscriptions = HashMap<Stream<T>, StreamSubscription>();  
18 -  
19 - T _value;  
20 - 8 +mixin RxObjectMixin<T> {
  9 + GetStream<T> subject = GetStream<T>();
  10 + final _subscriptions = <StreamSubscription>[];
21 bool get canUpdate => _subscriptions.isNotEmpty; 11 bool get canUpdate => _subscriptions.isNotEmpty;
22 12
23 - /// Makes this Rx looks like a function so you can update a new  
24 - /// value using [rx(someOtherValue)]. Practical to assign the Rx directly  
25 - /// to some Widget that has a signature ::onChange( value )  
26 - ///  
27 - /// Example:  
28 - /// ```  
29 - /// final myText = 'GetX rocks!'.obs;  
30 - ///  
31 - /// // in your Constructor, just to check it works :P  
32 - /// ever( myText, print ) ;  
33 - ///  
34 - /// // in your build(BuildContext) {  
35 - /// TextField(  
36 - /// onChanged: myText,  
37 - /// ),  
38 - ///```  
39 - T call([T v]) {  
40 - if (v != null) {  
41 - value = v;  
42 - }  
43 - return value;  
44 - } 13 + T _value;
45 14
46 /// Makes a direct update of [value] adding it to the Stream 15 /// Makes a direct update of [value] adding it to the Stream
47 /// useful when you make use of Rx for custom Types to referesh your UI. 16 /// useful when you make use of Rx for custom Types to referesh your UI.
@@ -65,31 +34,6 @@ abstract class _RxImpl<T> implements RxInterface<T> { @@ -65,31 +34,6 @@ abstract class _RxImpl<T> implements RxInterface<T> {
65 subject.add(value); 34 subject.add(value);
66 } 35 }
67 36
68 - /// Uses a callback to update [value] internally, similar to [refresh],  
69 - /// but provides the current value as the argument.  
70 - /// Makes sense for custom Rx types (like Models).  
71 - ///  
72 - /// Sample:  
73 - /// ```  
74 - /// class Person {  
75 - /// String name, last;  
76 - /// int age;  
77 - /// Person({this.name, this.last, this.age});  
78 - /// @override  
79 - /// String toString() => '$name $last, $age years old';  
80 - /// }  
81 - ///  
82 - /// final person = Person(name: 'John', last: 'Doe', age: 18).obs;  
83 - /// person.update((person) {  
84 - /// person.name = 'Roi';  
85 - /// });  
86 - /// print( person );  
87 - /// ```  
88 - void update(void fn(T val)) {  
89 - fn(_value);  
90 - subject.add(_value);  
91 - }  
92 -  
93 /// updates the value to [null] and adds it to the Stream. 37 /// updates the value to [null] and adds it to the Stream.
94 /// Even with null-safety coming, is still an important feature to support, as 38 /// Even with null-safety coming, is still an important feature to support, as
95 /// [call()] doesn't accept [null] values. For instance, 39 /// [call()] doesn't accept [null] values. For instance,
@@ -104,6 +48,53 @@ abstract class _RxImpl<T> implements RxInterface<T> { @@ -104,6 +48,53 @@ abstract class _RxImpl<T> implements RxInterface<T> {
104 subject.add(_value = null); 48 subject.add(_value = null);
105 } 49 }
106 50
  51 + /// Closes the subscriptions for this Rx, releasing the resources.
  52 + void close() {
  53 + for (final subscription in _subscriptions) {
  54 + subscription?.cancel();
  55 + }
  56 + _subscriptions.clear();
  57 + subject.close();
  58 + }
  59 +
  60 + /// Makes this Rx looks like a function so you can update a new
  61 + /// value using [rx(someOtherValue)]. Practical to assign the Rx directly
  62 + /// to some Widget that has a signature ::onChange( value )
  63 + ///
  64 + /// Example:
  65 + /// ```
  66 + /// final myText = 'GetX rocks!'.obs;
  67 + ///
  68 + /// // in your Constructor, just to check it works :P
  69 + /// ever( myText, print ) ;
  70 + ///
  71 + /// // in your build(BuildContext) {
  72 + /// TextField(
  73 + /// onChanged: myText,
  74 + /// ),
  75 + ///```
  76 + T call([T v]) {
  77 + if (v != null) {
  78 + value = v;
  79 + }
  80 + return value;
  81 + }
  82 +
  83 + /// This is an internal method.
  84 + /// Subscribe to changes on the inner stream.
  85 + void addListener(GetStream<T> rxGetx) {
  86 + if (_subscriptions.contains(rxGetx.listen)) {
  87 + return;
  88 + }
  89 +
  90 + final subs = rxGetx.listen((data) {
  91 + subject.add(data);
  92 + });
  93 + _subscriptions.add(subs);
  94 + }
  95 +
  96 + bool firstRebuild = true;
  97 +
107 /// Same as `toString()` but using a getter. 98 /// Same as `toString()` but using a getter.
108 String get string => value.toString(); 99 String get string => value.toString();
109 100
@@ -128,26 +119,6 @@ abstract class _RxImpl<T> implements RxInterface<T> { @@ -128,26 +119,6 @@ abstract class _RxImpl<T> implements RxInterface<T> {
128 // ignore: avoid_equals_and_hash_code_on_mutable_classes 119 // ignore: avoid_equals_and_hash_code_on_mutable_classes
129 int get hashCode => _value.hashCode; 120 int get hashCode => _value.hashCode;
130 121
131 - /// Closes the subscriptions for this Rx, releasing the resources.  
132 - void close() {  
133 - _subscriptions.forEach((observable, subscription) => subscription.cancel());  
134 - _subscriptions.clear();  
135 - subject.close();  
136 - }  
137 -  
138 - /// This is an internal method.  
139 - /// Subscribe to changes on the inner stream.  
140 - void addListener(Stream<T> rxGetx) {  
141 - if (_subscriptions.containsKey(rxGetx)) {  
142 - return;  
143 - }  
144 - _subscriptions[rxGetx] = rxGetx.listen((data) {  
145 - subject.add(data);  
146 - });  
147 - }  
148 -  
149 - bool firstRebuild = true;  
150 -  
151 /// Updates the [value] and adds it to the stream, updating the observer 122 /// Updates the [value] and adds it to the stream, updating the observer
152 /// Widget, only if it's different from the previous value. 123 /// Widget, only if it's different from the previous value.
153 set value(T val) { 124 set value(T val) {
@@ -160,26 +131,63 @@ abstract class _RxImpl<T> implements RxInterface<T> { @@ -160,26 +131,63 @@ abstract class _RxImpl<T> implements RxInterface<T> {
160 /// Returns the current [value] 131 /// Returns the current [value]
161 T get value { 132 T get value {
162 if (getObs != null) { 133 if (getObs != null) {
163 - getObs.addListener(subject.stream); 134 + getObs.addListener(subject);
164 } 135 }
165 return _value; 136 return _value;
166 } 137 }
167 138
168 - Stream<T> get stream => subject.stream; 139 + Stream<T> get stream => GetStreamTransformation<T>(subject.listenable);
169 140
170 - StreamSubscription<T> listen(void Function(T) onData,  
171 - {Function onError, void Function() onDone, bool cancelOnError}) =>  
172 - stream.listen(onData, onError: onError, onDone: onDone); 141 + StreamSubscription<T> listen(
  142 + void Function(T) onData, {
  143 + Function onError,
  144 + void Function() onDone,
  145 + bool cancelOnError = false,
  146 + }) =>
  147 + subject.listen(onData,
  148 + onError: onError, onDone: onDone, cancelOnError: cancelOnError);
173 149
174 /// Binds an existing [Stream<T>] to this Rx<T> to keep the values in sync. 150 /// Binds an existing [Stream<T>] to this Rx<T> to keep the values in sync.
175 /// You can bind multiple sources to update the value. 151 /// You can bind multiple sources to update the value.
176 /// Closing the subscription will happen automatically when the observer 152 /// Closing the subscription will happen automatically when the observer
177 /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree. 153 /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.
178 void bindStream(Stream<T> stream) { 154 void bindStream(Stream<T> stream) {
179 - _subscriptions[stream] = stream.listen((va) => value = va); 155 + _subscriptions.add(stream.listen((va) => value = va));
  156 + }
  157 +}
  158 +
  159 +/// Base Rx class that manages all the stream logic for any Type.
  160 +abstract class _RxImpl<T> with RxObjectMixin<T> implements RxInterface<T> {
  161 + _RxImpl(T initial) {
  162 + _value = initial;
180 } 163 }
181 164
182 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper); 165 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper);
  166 +
  167 + /// Uses a callback to update [value] internally, similar to [refresh],
  168 + /// but provides the current value as the argument.
  169 + /// Makes sense for custom Rx types (like Models).
  170 + ///
  171 + /// Sample:
  172 + /// ```
  173 + /// class Person {
  174 + /// String name, last;
  175 + /// int age;
  176 + /// Person({this.name, this.last, this.age});
  177 + /// @override
  178 + /// String toString() => '$name $last, $age years old';
  179 + /// }
  180 + ///
  181 + /// final person = Person(name: 'John', last: 'Doe', age: 18).obs;
  182 + /// person.update((person) {
  183 + /// person.name = 'Roi';
  184 + /// });
  185 + /// print( person );
  186 + /// ```
  187 + void update(void fn(T val)) {
  188 + fn(_value);
  189 + subject.add(_value);
  190 + }
183 } 191 }
184 192
185 /// Rx class for `bool` Type. 193 /// Rx class for `bool` Type.
@@ -202,6 +210,7 @@ class RxBool extends _RxImpl<bool> { @@ -202,6 +210,7 @@ class RxBool extends _RxImpl<bool> {
202 return this; 210 return this;
203 } 211 }
204 212
  213 + @override
205 String toString() { 214 String toString() {
206 return value ? "true" : "false"; 215 return value ? "true" : "false";
207 } 216 }
1 -import 'dart:async';  
2 -import '../rx_typedefs/rx_typedefs.dart'; 1 +part of rx_types;
3 2
4 /// This class is the foundation for all reactive (Rx) classes that makes Get 3 /// This class is the foundation for all reactive (Rx) classes that makes Get
5 /// so powerful. 4 /// so powerful.
@@ -8,10 +7,10 @@ import '../rx_typedefs/rx_typedefs.dart'; @@ -8,10 +7,10 @@ import '../rx_typedefs/rx_typedefs.dart';
8 abstract class RxInterface<T> { 7 abstract class RxInterface<T> {
9 RxInterface([T initial]); 8 RxInterface([T initial]);
10 9
11 - StreamController<T> subject; 10 + GetStream<T> subject;
12 11
13 /// Adds a listener to stream 12 /// Adds a listener to stream
14 - void addListener(Stream<T> rxGetx); 13 + void addListener(GetStream<T> rxGetx);
15 14
16 bool get canUpdate; 15 bool get canUpdate;
17 16
@@ -21,8 +20,10 @@ abstract class RxInterface<T> { @@ -21,8 +20,10 @@ abstract class RxInterface<T> {
21 20
22 /// Closes the stream 21 /// Closes the stream
23 // FIXME: shouldn't we expose the returned future? 22 // FIXME: shouldn't we expose the returned future?
24 - void close() => subject?.close(); 23 + void close();
25 24
26 /// Calls [callback] with current value, when the value changes. 25 /// Calls [callback] with current value, when the value changes.
27 - StreamSubscription<T> listen(ValueCallback<T> callback); 26 + StreamSubscription<T> listen(void Function(T event) onData,
  27 + {Function onError, void Function() onDone, bool cancelOnError});
28 } 28 }
  29 +
1 -part of 'rx_impl.dart'; 1 +part of rx_types;
2 2
3 /// Base Rx class for all num Rx's. 3 /// Base Rx class for all num Rx's.
4 abstract class _BaseRxNum<T extends num> extends _RxImpl<T> { 4 abstract class _BaseRxNum<T extends num> extends _RxImpl<T> {
@@ -299,23 +299,29 @@ class RxDouble extends _BaseRxNum<double> { @@ -299,23 +299,29 @@ class RxDouble extends _BaseRxNum<double> {
299 } 299 }
300 300
301 /// Multiplication operator. 301 /// Multiplication operator.
  302 + @override
302 double operator *(num other) => value * other; 303 double operator *(num other) => value * other;
303 304
  305 + @override
304 double operator %(num other) => value % other; 306 double operator %(num other) => value % other;
305 307
306 /// Division operator. 308 /// Division operator.
  309 + @override
307 double operator /(num other) => value / other; 310 double operator /(num other) => value / other;
308 311
309 /// Truncating division operator. 312 /// Truncating division operator.
310 /// 313 ///
311 /// The result of the truncating division `a ~/ b` is equivalent to 314 /// The result of the truncating division `a ~/ b` is equivalent to
312 /// `(a / b).truncate()`. 315 /// `(a / b).truncate()`.
  316 + @override
313 int operator ~/(num other) => value ~/ other; 317 int operator ~/(num other) => value ~/ other;
314 318
315 /// Negate operator. */ 319 /// Negate operator. */
  320 + @override
316 double operator -() => -value; 321 double operator -() => -value;
317 322
318 /// Returns the absolute value of this [double]. 323 /// Returns the absolute value of this [double].
  324 + @override
319 double abs() => value.abs(); 325 double abs() => value.abs();
320 326
321 /// Returns the sign of the double's numerical value. 327 /// Returns the sign of the double's numerical value.
@@ -323,6 +329,7 @@ class RxDouble extends _BaseRxNum<double> { @@ -323,6 +329,7 @@ class RxDouble extends _BaseRxNum<double> {
323 /// Returns -1.0 if the value is less than zero, 329 /// Returns -1.0 if the value is less than zero,
324 /// +1.0 if the value is greater than zero, 330 /// +1.0 if the value is greater than zero,
325 /// and the value itself if it is -0.0, 0.0 or NaN. 331 /// and the value itself if it is -0.0, 0.0 or NaN.
  332 + @override
326 double get sign => value.sign; 333 double get sign => value.sign;
327 334
328 /// Returns the integer closest to `this`. 335 /// Returns the integer closest to `this`.
@@ -331,22 +338,26 @@ class RxDouble extends _BaseRxNum<double> { @@ -331,22 +338,26 @@ class RxDouble extends _BaseRxNum<double> {
331 /// `(3.5).round() == 4` and `(-3.5).round() == -4`. 338 /// `(3.5).round() == 4` and `(-3.5).round() == -4`.
332 /// 339 ///
333 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. 340 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
  341 + @override
334 int round() => value.round(); 342 int round() => value.round();
335 343
336 /// Returns the greatest integer no greater than `this`. 344 /// Returns the greatest integer no greater than `this`.
337 /// 345 ///
338 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. 346 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
  347 + @override
339 int floor() => value.floor(); 348 int floor() => value.floor();
340 349
341 /// Returns the least integer no smaller than `this`. 350 /// Returns the least integer no smaller than `this`.
342 /// 351 ///
343 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. 352 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
  353 + @override
344 int ceil() => value.ceil(); 354 int ceil() => value.ceil();
345 355
346 /// Returns the integer obtained by discarding any fractional 356 /// Returns the integer obtained by discarding any fractional
347 /// digits from `this`. 357 /// digits from `this`.
348 /// 358 ///
349 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. 359 /// If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
  360 + @override
350 int truncate() => value.truncate(); 361 int truncate() => value.truncate();
351 362
352 /// Returns the integer double value closest to `this`. 363 /// Returns the integer double value closest to `this`.
@@ -361,6 +372,7 @@ class RxDouble extends _BaseRxNum<double> { @@ -361,6 +372,7 @@ class RxDouble extends _BaseRxNum<double> {
361 /// and `-0.0` is therefore considered closer to negative numbers than `0.0`. 372 /// and `-0.0` is therefore considered closer to negative numbers than `0.0`.
362 /// This means that for a value, `d` in the range `-0.5 < d < 0.0`, 373 /// This means that for a value, `d` in the range `-0.5 < d < 0.0`,
363 /// the result is `-0.0`. 374 /// the result is `-0.0`.
  375 + @override
364 double roundToDouble() => value.roundToDouble(); 376 double roundToDouble() => value.roundToDouble();
365 377
366 /// Returns the greatest integer double value no greater than `this`. 378 /// Returns the greatest integer double value no greater than `this`.
@@ -370,6 +382,7 @@ class RxDouble extends _BaseRxNum<double> { @@ -370,6 +382,7 @@ class RxDouble extends _BaseRxNum<double> {
370 /// 382 ///
371 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`. 383 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
372 /// A number `d` in the range `0.0 < d < 1.0` will return `0.0`. 384 /// A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
  385 + @override
373 double floorToDouble() => value.floorToDouble(); 386 double floorToDouble() => value.floorToDouble();
374 387
375 /// Returns the least integer double value no smaller than `this`. 388 /// Returns the least integer double value no smaller than `this`.
@@ -379,6 +392,7 @@ class RxDouble extends _BaseRxNum<double> { @@ -379,6 +392,7 @@ class RxDouble extends _BaseRxNum<double> {
379 /// 392 ///
380 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`. 393 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
381 /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`. 394 /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
  395 + @override
382 double ceilToDouble() => value.ceilToDouble(); 396 double ceilToDouble() => value.ceilToDouble();
383 397
384 /// Returns the integer double value obtained by discarding any fractional 398 /// Returns the integer double value obtained by discarding any fractional
@@ -390,6 +404,7 @@ class RxDouble extends _BaseRxNum<double> { @@ -390,6 +404,7 @@ class RxDouble extends _BaseRxNum<double> {
390 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`. 404 /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
391 /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and 405 /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
392 /// in the range `0.0 < d < 1.0` it will return 0.0. 406 /// in the range `0.0 < d < 1.0` it will return 0.0.
  407 + @override
393 double truncateToDouble() => value.truncateToDouble(); 408 double truncateToDouble() => value.truncateToDouble();
394 } 409 }
395 410
@@ -578,40 +593,51 @@ class RxInt extends _BaseRxNum<int> { @@ -578,40 +593,51 @@ class RxInt extends _BaseRxNum<int> {
578 /// 593 ///
579 /// The result of negating an integer always has the opposite sign, except 594 /// The result of negating an integer always has the opposite sign, except
580 /// for zero, which is its own negation. 595 /// for zero, which is its own negation.
  596 + @override
581 int operator -() => -value; 597 int operator -() => -value;
582 598
583 /// Returns the absolute value of this integer. 599 /// Returns the absolute value of this integer.
584 /// 600 ///
585 /// For any integer `x`, the result is the same as `x < 0 ? -x : x`. 601 /// For any integer `x`, the result is the same as `x < 0 ? -x : x`.
  602 + @override
586 int abs() => value.abs(); 603 int abs() => value.abs();
587 604
588 /// Returns the sign of this integer. 605 /// Returns the sign of this integer.
589 /// 606 ///
590 /// Returns 0 for zero, -1 for values less than zero and 607 /// Returns 0 for zero, -1 for values less than zero and
591 /// +1 for values greater than zero. 608 /// +1 for values greater than zero.
  609 + @override
592 int get sign => value.sign; 610 int get sign => value.sign;
593 611
594 /// Returns `this`. 612 /// Returns `this`.
  613 + @override
595 int round() => value.round(); 614 int round() => value.round();
596 615
597 /// Returns `this`. 616 /// Returns `this`.
  617 + @override
598 int floor() => value.floor(); 618 int floor() => value.floor();
599 619
600 /// Returns `this`. 620 /// Returns `this`.
  621 + @override
601 int ceil() => value.ceil(); 622 int ceil() => value.ceil();
602 623
603 /// Returns `this`. 624 /// Returns `this`.
  625 + @override
604 int truncate() => value.truncate(); 626 int truncate() => value.truncate();
605 627
606 /// Returns `this.toDouble()`. 628 /// Returns `this.toDouble()`.
  629 + @override
607 double roundToDouble() => value.roundToDouble(); 630 double roundToDouble() => value.roundToDouble();
608 631
609 /// Returns `this.toDouble()`. 632 /// Returns `this.toDouble()`.
  633 + @override
610 double floorToDouble() => value.floorToDouble(); 634 double floorToDouble() => value.floorToDouble();
611 635
612 /// Returns `this.toDouble()`. 636 /// Returns `this.toDouble()`.
  637 + @override
613 double ceilToDouble() => value.ceilToDouble(); 638 double ceilToDouble() => value.ceilToDouble();
614 639
615 /// Returns `this.toDouble()`. 640 /// Returns `this.toDouble()`.
  641 + @override
616 double truncateToDouble() => value.truncateToDouble(); 642 double truncateToDouble() => value.truncateToDouble();
617 } 643 }
  1 +part of rx_types;
  2 +
  3 +/// Create a list similar to `List<T>`
  4 +class RxList<E> extends ListMixin<E>
  5 + with RxObjectMixin<List<E>>
  6 + implements RxInterface<List<E>> {
  7 + RxList([List<E> initial]) {
  8 + _value = initial;
  9 + }
  10 +
  11 + @override
  12 + Iterator<E> get iterator => value.iterator;
  13 +
  14 + @override
  15 + void operator []=(int index, E val) {
  16 + _value[index] = val;
  17 + refresh();
  18 + }
  19 +
  20 + /// Special override to push() element(s) in a reactive way
  21 + /// inside the List,
  22 + @override
  23 + RxList<E> operator +(Iterable<E> val) {
  24 + addAll(val);
  25 + refresh();
  26 + return this;
  27 + }
  28 +
  29 + @override
  30 + E operator [](int index) {
  31 + return value[index];
  32 + }
  33 +
  34 + @override
  35 + void add(E item) {
  36 + _value.add(item);
  37 + refresh();
  38 + }
  39 +
  40 + @override
  41 + void addAll(Iterable<E> item) {
  42 + _value.addAll(item);
  43 + refresh();
  44 + }
  45 +
  46 + /// Add [item] to [List<E>] only if [item] is not null.
  47 + void addNonNull(E item) {
  48 + if (item != null) add(item);
  49 + }
  50 +
  51 + /// Add [Iterable<E>] to [List<E>] only if [Iterable<E>] is not null.
  52 + void addAllNonNull(Iterable<E> item) {
  53 + if (item != null) addAll(item);
  54 + }
  55 +
  56 + /// Add [item] to [List<E>] only if [condition] is true.
  57 + void addIf(dynamic condition, E item) {
  58 + if (condition is Condition) condition = condition();
  59 + if (condition is bool && condition) add(item);
  60 + }
  61 +
  62 + /// Adds [Iterable<E>] to [List<E>] only if [condition] is true.
  63 + void addAllIf(dynamic condition, Iterable<E> items) {
  64 + if (condition is Condition) condition = condition();
  65 + if (condition is bool && condition) addAll(items);
  66 + }
  67 +
  68 + @override
  69 + int get length => value.length;
  70 +
  71 + /// Replaces all existing items of this list with [item]
  72 + void assign(E item) {
  73 + clear();
  74 + add(item);
  75 + }
  76 +
  77 + /// Replaces all existing items of this list with [items]
  78 + void assignAll(Iterable<E> items) {
  79 + clear();
  80 + addAll(items);
  81 + }
  82 +
  83 + @override
  84 + @protected
  85 + List<E> get value {
  86 + if (getObs != null) {
  87 + getObs.addListener(subject);
  88 + }
  89 + return _value;
  90 + }
  91 +
  92 + @override
  93 + @protected
  94 + @Deprecated('List.value is deprecated. use [yourList.assignAll(newList)]')
  95 + set value(List<E> val) {
  96 + if (_value == val) return;
  97 + _value = val;
  98 + refresh();
  99 + }
  100 +
  101 + @override
  102 + set length(int newLength) {
  103 + _value.length = newLength;
  104 + refresh();
  105 + }
  106 +
  107 + @override
  108 + void insertAll(int index, Iterable<E> iterable) {
  109 + _value.insertAll(index, iterable);
  110 + refresh();
  111 + }
  112 +
  113 + @override
  114 + Iterable<E> get reversed => value.reversed;
  115 +
  116 + @override
  117 + Iterable<E> where(bool Function(E) test) {
  118 + return value.where(test);
  119 + }
  120 +
  121 + @override
  122 + Iterable<T> whereType<T>() {
  123 + return value.whereType<T>();
  124 + }
  125 +
  126 + @override
  127 + void sort([int compare(E a, E b)]) {
  128 + _value.sort(compare);
  129 + refresh();
  130 + }
  131 +}
  132 +
  133 +// /// Create a list similar to `List<T>`
  134 +// class RxList<E> implements List<E>, RxInterface<List<E>> {
  135 +// RxList([List<E> initial]) {
  136 +// if (initial != null) _value = initial;
  137 +// }
  138 +
  139 +// List<E> _value = <E>[];
  140 +
  141 +// @override
  142 +// Iterator<E> get iterator => value.iterator;
  143 +
  144 +// @override
  145 +// bool get isEmpty => value.isEmpty;
  146 +
  147 +// bool get canUpdate {
  148 +// return _subscriptions.length > 0;
  149 +// }
  150 +
  151 +// @override
  152 +// bool get isNotEmpty => value.isNotEmpty;
  153 +
  154 +// @override
  155 +// StreamController<List<E>> subject = StreamController.broadcast();
  156 +
  157 +// final _subscriptions = HashMap<Stream<List<E>>, StreamSubscription>();
  158 +
  159 +// void operator []=(int index, E val) {
  160 +// _value[index] = val;
  161 +// refresh();
  162 +// }
  163 +
  164 +// void refresh() {
  165 +// subject.add(_value);
  166 +// }
  167 +
  168 +// /// Special override to push() element(s) in a reactive way
  169 +// /// inside the List,
  170 +// RxList<E> operator +(Iterable<E> val) {
  171 +// addAll(val);
  172 +// refresh();
  173 +// return this;
  174 +// }
  175 +
  176 +// E operator [](int index) {
  177 +// return value[index];
  178 +// }
  179 +
  180 +// void add(E item) {
  181 +// _value.add(item);
  182 +// refresh();
  183 +// }
  184 +
  185 +// @override
  186 +// void addAll(Iterable<E> item) {
  187 +// _value.addAll(item);
  188 +// refresh();
  189 +// }
  190 +
  191 +// /// Add [item] to [List<E>] only if [item] is not null.
  192 +// void addNonNull(E item) {
  193 +// if (item != null) add(item);
  194 +// }
  195 +
  196 +// /// Add [Iterable<E>] to [List<E>] only if [Iterable<E>] is not null.
  197 +// void addAllNonNull(Iterable<E> item) {
  198 +// if (item != null) addAll(item);
  199 +// }
  200 +
  201 +// /// Add [item] to [List<E>] only if [condition] is true.
  202 +// void addIf(dynamic condition, E item) {
  203 +// if (condition is Condition) condition = condition();
  204 +// if (condition is bool && condition) add(item);
  205 +// }
  206 +
  207 +// /// Adds [Iterable<E>] to [List<E>] only if [condition] is true.
  208 +// void addAllIf(dynamic condition, Iterable<E> items) {
  209 +// if (condition is Condition) condition = condition();
  210 +// if (condition is bool && condition) addAll(items);
  211 +// }
  212 +
  213 +// @override
  214 +// void insert(int index, E item) {
  215 +// _value.insert(index, item);
  216 +// refresh();
  217 +// }
  218 +
  219 +// @override
  220 +// void insertAll(int index, Iterable<E> iterable) {
  221 +// _value.insertAll(index, iterable);
  222 +// refresh();
  223 +// }
  224 +
  225 +// @override
  226 +// int get length => value.length;
  227 +
  228 +// /// Removes an item from the list.
  229 +// ///
  230 +// /// This is O(N) in the number of items in the list.
  231 +// ///
  232 +// /// Returns whether the item was present in the list.
  233 +// @override
  234 +// bool remove(Object item) {
  235 +// final hasRemoved = _value.remove(item);
  236 +// if (hasRemoved) {
  237 +// refresh();
  238 +// }
  239 +// return hasRemoved;
  240 +// }
  241 +
  242 +// @override
  243 +// E removeAt(int index) {
  244 +// final item = _value.removeAt(index);
  245 +// refresh();
  246 +// return item;
  247 +// }
  248 +
  249 +// @override
  250 +// E removeLast() {
  251 +// final item = _value.removeLast();
  252 +// refresh();
  253 +// return item;
  254 +// }
  255 +
  256 +// @override
  257 +// void removeRange(int start, int end) {
  258 +// _value.removeRange(start, end);
  259 +// refresh();
  260 +// }
  261 +
  262 +// @override
  263 +// void removeWhere(bool Function(E) test) {
  264 +// _value.removeWhere(test);
  265 +// refresh();
  266 +// }
  267 +
  268 +// @override
  269 +// void clear() {
  270 +// _value.clear();
  271 +// refresh();
  272 +// }
  273 +
  274 +// @override
  275 +// void sort([int compare(E a, E b)]) {
  276 +// _value.sort(compare);
  277 +// refresh();
  278 +// }
  279 +
  280 +// @override
  281 +// void close() {
  282 +// _subscriptions.forEach((observable, subscription) {
  283 +// subscription.cancel();
  284 +// });
  285 +// _subscriptions.clear();
  286 +// subject.close();
  287 +// }
  288 +
  289 +// /// Replaces all existing items of this list with [item]
  290 +// void assign(E item) {
  291 +// clear();
  292 +// add(item);
  293 +// }
  294 +
  295 +// void update(void fn(Iterable<E> value)) {
  296 +// fn(value);
  297 +// refresh();
  298 +// }
  299 +
  300 +// /// Replaces all existing items of this list with [items]
  301 +// void assignAll(Iterable<E> items) {
  302 +// clear();
  303 +// addAll(items);
  304 +// }
  305 +
  306 +// @protected
  307 +// List<E> get value {
  308 +// if (getObs != null) {
  309 +// getObs.addListener(subject.stream);
  310 +// }
  311 +// return _value;
  312 +// }
  313 +
  314 +// String get string => value.toString();
  315 +
  316 +// void addListener(Stream<List<E>> rxGetX) {
  317 +// if (_subscriptions.containsKey(rxGetX)) {
  318 +// return;
  319 +// }
  320 +// _subscriptions[rxGetX] = rxGetX.listen(subject.add);
  321 +// }
  322 +
  323 +// set value(List<E> val) {
  324 +// if (_value == val) return;
  325 +// _value = val;
  326 +// refresh();
  327 +// }
  328 +
  329 +// Stream<List<E>> get stream => subject.stream;
  330 +
  331 +// StreamSubscription<List<E>> listen(
  332 +// void Function(List<E>) onData, {
  333 +// Function onError,
  334 +// void Function() onDone,
  335 +// bool cancelOnError,
  336 +// }) =>
  337 +// stream.listen(onData, onError: onError, onDone: onDone);
  338 +
  339 +// /// Binds an existing [Stream<List>] to this [RxList].
  340 +// /// You can bind multiple sources to update the value.
  341 +// /// Closing the subscription will happen automatically when the observer
  342 +// /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.
  343 +// void bindStream(Stream<List<E>> stream) {
  344 +// _subscriptions[stream] = stream.listen((va) => value = va);
  345 +// }
  346 +
  347 +// @override
  348 +// E get first => value.first;
  349 +
  350 +// @override
  351 +// E get last => value.last;
  352 +
  353 +// @override
  354 +// bool any(bool Function(E) test) {
  355 +// return value.any(test);
  356 +// }
  357 +
  358 +// @override
  359 +// Map<int, E> asMap() {
  360 +// return value.asMap();
  361 +// }
  362 +
  363 +// @override
  364 +// List<R> cast<R>() {
  365 +// return value.cast<R>();
  366 +// }
  367 +
  368 +// @override
  369 +// bool contains(Object element) {
  370 +// return value.contains(element);
  371 +// }
  372 +
  373 +// @override
  374 +// E elementAt(int index) {
  375 +// return value.elementAt(index);
  376 +// }
  377 +
  378 +// @override
  379 +// bool every(bool Function(E) test) {
  380 +// return value.every(test);
  381 +// }
  382 +
  383 +// @override
  384 +// Iterable<T> expand<T>(Iterable<T> Function(E) f) {
  385 +// return value.expand(f);
  386 +// }
  387 +
  388 +// @override
  389 +// void fillRange(int start, int end, [E fillValue]) {
  390 +// _value.fillRange(start, end, fillValue);
  391 +// refresh();
  392 +// }
  393 +
  394 +// @override
  395 +// E firstWhere(bool Function(E) test, {E Function() orElse}) {
  396 +// return value.firstWhere(test, orElse: orElse);
  397 +// }
  398 +
  399 +// @override
  400 +// T fold<T>(T initialValue, T Function(T, E) combine) {
  401 +// return value.fold(initialValue, combine);
  402 +// }
  403 +
  404 +// @override
  405 +// Iterable<E> followedBy(Iterable<E> other) {
  406 +// return value.followedBy(other);
  407 +// }
  408 +
  409 +// @override
  410 +// void forEach(void Function(E) f) {
  411 +// value.forEach(f);
  412 +// }
  413 +
  414 +// @override
  415 +// Iterable<E> getRange(int start, int end) {
  416 +// return value.getRange(start, end);
  417 +// }
  418 +
  419 +// @override
  420 +// int indexOf(E element, [int start = 0]) {
  421 +// return value.indexOf(element, start);
  422 +// }
  423 +
  424 +// @override
  425 +// int indexWhere(bool Function(E) test, [int start = 0]) {
  426 +// return value.indexWhere(test, start);
  427 +// }
  428 +
  429 +// @override
  430 +// String join([String separator = ""]) {
  431 +// return value.join(separator);
  432 +// }
  433 +
  434 +// @override
  435 +// int lastIndexOf(E element, [int start]) {
  436 +// return value.lastIndexOf(element, start);
  437 +// }
  438 +
  439 +// @override
  440 +// int lastIndexWhere(bool Function(E) test, [int start]) {
  441 +// return value.lastIndexWhere(test, start);
  442 +// }
  443 +
  444 +// @override
  445 +// E lastWhere(bool Function(E) test, {E Function() orElse}) {
  446 +// return value.lastWhere(test, orElse: orElse);
  447 +// }
  448 +
  449 +// @override
  450 +// set length(int newLength) {
  451 +// _value.length = newLength;
  452 +// refresh();
  453 +// }
  454 +
  455 +// @override
  456 +// Iterable<T> map<T>(T Function(E) f) {
  457 +// return value.map(f);
  458 +// }
  459 +
  460 +// @override
  461 +// E reduce(E Function(E, E) combine) {
  462 +// return value.reduce(combine);
  463 +// }
  464 +
  465 +// @override
  466 +// void replaceRange(int start, int end, Iterable<E> replacement) {
  467 +// _value.replaceRange(start, end, replacement);
  468 +// refresh();
  469 +// }
  470 +
  471 +// @override
  472 +// void retainWhere(bool Function(E) test) {
  473 +// _value.retainWhere(test);
  474 +// refresh();
  475 +// }
  476 +
  477 +// @override
  478 +// Iterable<E> get reversed => value.reversed;
  479 +
  480 +// @override
  481 +// void setAll(int index, Iterable<E> iterable) {
  482 +// _value.setAll(index, iterable);
  483 +// refresh();
  484 +// }
  485 +
  486 +// @override
  487 +// void setRange(int start, int end,
  488 +// Iterable<E> iterable, [int skipCount = 0],) {
  489 +// _value.setRange(start, end, iterable, skipCount);
  490 +// refresh();
  491 +// }
  492 +
  493 +// @override
  494 +// void shuffle([Random random]) {
  495 +// _value.shuffle(random);
  496 +// refresh();
  497 +// }
  498 +
  499 +// @override
  500 +// E get single => value.single;
  501 +
  502 +// @override
  503 +// E singleWhere(bool Function(E) test, {E Function() orElse}) {
  504 +// return value.singleWhere(test, orElse: orElse);
  505 +// }
  506 +
  507 +// @override
  508 +// Iterable<E> skip(int count) {
  509 +// return value.skip(count);
  510 +// }
  511 +
  512 +// @override
  513 +// Iterable<E> skipWhile(bool Function(E) test) {
  514 +// return value.skipWhile(test);
  515 +// }
  516 +
  517 +// @override
  518 +// List<E> sublist(int start, [int end]) {
  519 +// return value.sublist(start, end);
  520 +// }
  521 +
  522 +// @override
  523 +// Iterable<E> take(int count) {
  524 +// return value.take(count);
  525 +// }
  526 +
  527 +// @override
  528 +// Iterable<E> takeWhile(bool Function(E) test) {
  529 +// return value.takeWhile(test);
  530 +// }
  531 +
  532 +// @override
  533 +// List<E> toList({bool growable = true}) {
  534 +// return value.toList(growable: growable);
  535 +// }
  536 +
  537 +// @override
  538 +// Set<E> toSet() {
  539 +// return value.toSet();
  540 +// }
  541 +
  542 +// @override
  543 +// Iterable<E> where(bool Function(E) test) {
  544 +// return value.where(test);
  545 +// }
  546 +
  547 +// @override
  548 +// Iterable<T> whereType<T>() {
  549 +// return value.whereType<T>();
  550 +// }
  551 +
  552 +// @override
  553 +// set first(E value) {
  554 +// _value.first = value;
  555 +// refresh();
  556 +// }
  557 +
  558 +// @override
  559 +// set last(E value) {
  560 +// _value.last = value;
  561 +// refresh();
  562 +// }
  563 +// }
  564 +
  565 +extension ListExtension<E> on List<E> {
  566 + RxList<E> get obs {
  567 + if (this != null) {
  568 + return RxList<E>(<E>[])..addAllNonNull(this);
  569 + } else {
  570 + return RxList<E>(null);
  571 + }
  572 + }
  573 +}
1 -import 'dart:async';  
2 -import 'dart:collection';  
3 -import 'package:flutter/foundation.dart';  
4 -import '../rx_core/rx_impl.dart';  
5 -import '../rx_core/rx_interface.dart';  
6 -import '../rx_typedefs/rx_typedefs.dart'; 1 +part of rx_types;
7 2
8 -class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> { 3 +class RxMap<K, V> extends MapMixin<K, V>
  4 + with RxObjectMixin<Map<K, V>>
  5 + implements RxInterface<Map<K, V>> {
9 RxMap([Map<K, V> initial]) { 6 RxMap([Map<K, V> initial]) {
10 - if (initial != null) _value = initial;  
11 - }  
12 -  
13 - @override  
14 - StreamController<Map<K, V>> subject = StreamController<Map<K, V>>.broadcast();  
15 - final _subscriptions = HashMap<Stream<Map<K, V>>, StreamSubscription>();  
16 -  
17 - Map<K, V> _value;  
18 -  
19 - @protected  
20 - Map<K, V> get value {  
21 - if (getObs != null) {  
22 - getObs.addListener(subject.stream);  
23 - }  
24 - return _value;  
25 - }  
26 -  
27 - void refresh() {  
28 - subject.add(_value);  
29 - }  
30 -  
31 - String get string => value.toString();  
32 -  
33 - bool get canUpdate {  
34 - return _subscriptions.length > 0;  
35 - }  
36 -  
37 - @override  
38 - void close() {  
39 - _subscriptions.forEach((observable, subscription) {  
40 - subscription.cancel();  
41 - });  
42 - _subscriptions.clear();  
43 - subject.close();  
44 - }  
45 -  
46 - @override  
47 - void addListener(Stream<Map<K, V>> rxGetX) {  
48 - if (_subscriptions.containsKey(rxGetX)) {  
49 - return;  
50 - }  
51 - _subscriptions[rxGetX] = rxGetX.listen((data) {  
52 - subject.add(data);  
53 - });  
54 - }  
55 -  
56 - set value(Map<K, V> val) {  
57 - if (_value == val) return;  
58 - _value = val;  
59 - refresh();  
60 - }  
61 -  
62 - Stream<Map<K, V>> get stream => subject.stream;  
63 -  
64 - StreamSubscription<Map<K, V>> listen(void Function(Map<K, V>) onData,  
65 - {Function onError, void Function() onDone, bool cancelOnError}) =>  
66 - stream.listen(onData, onError: onError, onDone: onDone);  
67 -  
68 - /// Binds an existing [Stream<Map>] to this [RxMap].  
69 - /// You can bind multiple sources to update the value.  
70 - /// Closing the subscription will happen automatically when the observer  
71 - /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.  
72 - void bindStream(Stream<Map<K, V>> stream) {  
73 - _subscriptions[stream] = stream.listen((va) => value = va);  
74 - }  
75 -  
76 - void add(K key, V value) {  
77 - _value[key] = value;  
78 - refresh();  
79 - }  
80 -  
81 - void addIf(dynamic condition, K key, V value) {  
82 - if (condition is Condition) condition = condition();  
83 - if (condition is bool && condition) {  
84 - _value[key] = value;  
85 - refresh();  
86 - }  
87 - }  
88 -  
89 - void addAllIf(dynamic condition, Map<K, V> values) {  
90 - if (condition is Condition) condition = condition();  
91 - if (condition is bool && condition) addAll(values); 7 + _value = initial;
92 } 8 }
93 9
94 @override 10 @override
@@ -103,64 +19,15 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> { @@ -103,64 +19,15 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
103 } 19 }
104 20
105 @override 21 @override
106 - void addAll(Map<K, V> other) {  
107 - _value.addAll(other);  
108 - refresh();  
109 - }  
110 -  
111 - @override  
112 - void addEntries(Iterable<MapEntry<K, V>> entries) {  
113 - _value.addEntries(entries);  
114 - refresh();  
115 - }  
116 -  
117 - @override  
118 void clear() { 22 void clear() {
119 _value.clear(); 23 _value.clear();
120 refresh(); 24 refresh();
121 } 25 }
122 26
123 @override 27 @override
124 - Map<K2, V2> cast<K2, V2>() => value.cast<K2, V2>();  
125 -  
126 - @override  
127 - bool containsKey(Object key) => value.containsKey(key);  
128 -  
129 - @override  
130 - bool containsValue(Object value) => _value.containsValue(value);  
131 -  
132 - @override  
133 - Iterable<MapEntry<K, V>> get entries => value.entries;  
134 -  
135 - @override  
136 - void forEach(void Function(K, V) f) {  
137 - value.forEach(f);  
138 - }  
139 -  
140 - @override  
141 - bool get isEmpty => value.isEmpty;  
142 -  
143 - @override  
144 - bool get isNotEmpty => value.isNotEmpty;  
145 -  
146 - @override  
147 Iterable<K> get keys => value.keys; 28 Iterable<K> get keys => value.keys;
148 29
149 @override 30 @override
150 - int get length => value.length;  
151 -  
152 - @override  
153 - Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> Function(K, V) transform) =>  
154 - value.map(transform);  
155 -  
156 - @override  
157 - V putIfAbsent(K key, V Function() ifAbsent) {  
158 - final val = _value.putIfAbsent(key, ifAbsent);  
159 - refresh();  
160 - return val;  
161 - }  
162 -  
163 - @override  
164 V remove(Object key) { 31 V remove(Object key) {
165 final val = _value.remove(key); 32 final val = _value.remove(key);
166 refresh(); 33 refresh();
@@ -168,37 +35,51 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> { @@ -168,37 +35,51 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
168 } 35 }
169 36
170 @override 37 @override
171 - void removeWhere(bool Function(K, V) test) {  
172 - _value.removeWhere(test);  
173 - refresh(); 38 + @protected
  39 + Map<K, V> get value {
  40 + if (getObs != null) {
  41 + getObs.addListener(subject);
  42 + }
  43 + return _value;
174 } 44 }
175 45
176 - @override  
177 - Iterable<V> get values => value.values;  
178 -  
179 - @override  
180 - String toString() => _value.toString(); 46 + void assign(K key, V val) {
  47 + _value.clear();
  48 + _value[key] = val;
  49 + refresh();
  50 + }
181 51
182 - @override  
183 - V update(K key, V Function(V) update, {V Function() ifAbsent}) {  
184 - final val = _value.update(key, update, ifAbsent: ifAbsent); 52 + void assignAll(Map<K, V> val) {
  53 + if (_value == val) return;
  54 + _value = val;
185 refresh(); 55 refresh();
186 - return val;  
187 } 56 }
188 57
189 @override 58 @override
190 - void updateAll(V Function(K, V) update) {  
191 - _value.updateAll(update); 59 + @protected
  60 + @Deprecated('Map.value is deprecated. use [yourMap.assignAll(newMap)]')
  61 + set value(Map<K, V> val) {
  62 + if (_value == val) return;
  63 + _value = val;
192 refresh(); 64 refresh();
193 } 65 }
  66 +
  67 + void addIf(dynamic condition, K key, V value) {
  68 + if (condition is Condition) condition = condition();
  69 + if (condition is bool && condition) {
  70 + _value[key] = value;
  71 + refresh();
  72 + }
  73 + }
  74 +
  75 + void addAllIf(dynamic condition, Map<K, V> values) {
  76 + if (condition is Condition) condition = condition();
  77 + if (condition is bool && condition) addAll(values);
  78 + }
194 } 79 }
195 80
196 extension MapExtension<K, V> on Map<K, V> { 81 extension MapExtension<K, V> on Map<K, V> {
197 RxMap<K, V> get obs { 82 RxMap<K, V> get obs {
198 - if (this != null) {  
199 - return RxMap<K, V>(<K, V>{})..addAll(this);  
200 - } else {  
201 - return RxMap<K, V>(null);  
202 - } 83 + return RxMap<K, V>(this);
203 } 84 }
204 } 85 }
  1 +part of rx_types;
  2 +
  3 +class RxSet<E> extends SetMixin<E>
  4 + with RxObjectMixin<Set<E>>
  5 + implements RxInterface<Set<E>> {
  6 + RxSet([Set<E> initial]) {
  7 + if (initial != null) _value = initial;
  8 + }
  9 +
  10 + /// Adds [item] only if [condition] resolves to true.
  11 + void addIf(dynamic condition, E item) {
  12 + if (condition is Condition) condition = condition();
  13 + if (condition is bool && condition) add(item);
  14 + }
  15 +
  16 + /// Adds all [items] only if [condition] resolves to true.
  17 + void addAllIf(dynamic condition, Iterable<E> items) {
  18 + if (condition is Condition) condition = condition();
  19 + if (condition is bool && condition) addAll(items);
  20 + }
  21 +
  22 + /// Special override to push() element(s) in a reactive way
  23 + /// inside the List,
  24 + RxSet<E> operator +(Set<E> val) {
  25 + addAll(val);
  26 + refresh();
  27 + return this;
  28 + }
  29 +
  30 + /// Adds only if [item] is not null.
  31 + void addNonNull(E item) {
  32 + if (item != null) add(item);
  33 + }
  34 +
  35 + /// Adds only if [item] is not null.
  36 + void addAllNonNull(Iterable<E> item) {
  37 + if (item != null) addAll(item);
  38 + }
  39 +
  40 + /// Replaces all existing items of this list with [item]
  41 + void assign(E item) {
  42 + clear();
  43 + add(item);
  44 + }
  45 +
  46 + void update(void fn(Iterable<E> value)) {
  47 + fn(value);
  48 + refresh();
  49 + }
  50 +
  51 + /// Replaces all existing items of this list with [items]
  52 + void assignAll(Iterable<E> items) {
  53 + clear();
  54 + addAll(items);
  55 + }
  56 +
  57 + @override
  58 + @protected
  59 + Set<E> get value {
  60 + if (getObs != null) {
  61 + getObs.addListener(subject);
  62 + }
  63 + return _value;
  64 + }
  65 +
  66 + @override
  67 + @protected
  68 + set value(Set<E> val) {
  69 + if (_value == val) return;
  70 + _value = val;
  71 + refresh();
  72 + }
  73 +
  74 +
  75 +
  76 + @override
  77 + bool add(E value) {
  78 + final val = _value.add(value);
  79 + refresh();
  80 + return val;
  81 + }
  82 +
  83 + @override
  84 + bool contains(Object element) {
  85 + return value.contains(element);
  86 + }
  87 +
  88 + @override
  89 + Iterator<E> get iterator => value.iterator;
  90 +
  91 + @override
  92 + int get length => value.length;
  93 +
  94 + @override
  95 + E lookup(Object object) {
  96 + return value.lookup(object);
  97 + }
  98 +
  99 + @override
  100 + bool remove(Object item) {
  101 + var hasRemoved = _value.remove(item);
  102 + if (hasRemoved) {
  103 + refresh();
  104 + }
  105 + return hasRemoved;
  106 + }
  107 +
  108 + @override
  109 + Set<E> toSet() {
  110 + return value.toSet();
  111 + }
  112 +
  113 + @override
  114 + void addAll(Iterable<E> item) {
  115 + _value.addAll(item);
  116 + refresh();
  117 + }
  118 +
  119 + @override
  120 + void clear() {
  121 + _value.clear();
  122 + refresh();
  123 + }
  124 +
  125 + @override
  126 + void removeAll(Iterable<Object> elements) {
  127 + _value.removeAll(elements);
  128 + refresh();
  129 + }
  130 +
  131 + @override
  132 + void retainAll(Iterable<Object> elements) {
  133 + _value.retainAll(elements);
  134 + refresh();
  135 + }
  136 +
  137 + @override
  138 + void retainWhere(bool Function(E) E) {
  139 + _value.retainWhere(E);
  140 + refresh();
  141 + }
  142 +}
  143 +
  144 +// class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
  145 +// RxSet([Set<E> initial]) {
  146 +// if (initial != null) _value = initial;
  147 +// }
  148 +
  149 +// Set<E> _value = <E>{};
  150 +
  151 +// @override
  152 +// Iterator<E> get iterator => value.iterator;
  153 +
  154 +// @override
  155 +// bool get isEmpty => value.isEmpty;
  156 +
  157 +// bool get canUpdate {
  158 +// return _subscriptions.length > 0;
  159 +// }
  160 +
  161 +// @override
  162 +// bool get isNotEmpty => value.isNotEmpty;
  163 +
  164 +// StreamController<Set<E>> subject = StreamController<Set<E>>.broadcast();
  165 +// final _subscriptions = HashMap<Stream<Set<E>>, StreamSubscription>();
  166 +
  167 +// /// Adds [item] only if [condition] resolves to true.
  168 +// void addIf(dynamic condition, E item) {
  169 +// if (condition is Condition) condition = condition();
  170 +// if (condition is bool && condition) add(item);
  171 +// }
  172 +
  173 +// /// Adds all [items] only if [condition] resolves to true.
  174 +// void addAllIf(dynamic condition, Iterable<E> items) {
  175 +// if (condition is Condition) condition = condition();
  176 +// if (condition is bool && condition) addAll(items);
  177 +// }
  178 +
  179 +// void refresh() {
  180 +// subject.add(_value);
  181 +// }
  182 +
  183 +// /// Special override to push() element(s) in a reactive way
  184 +// /// inside the List,
  185 +// RxSet<E> operator +(Set<E> val) {
  186 +// addAll(val);
  187 +// refresh();
  188 +// return this;
  189 +// }
  190 +
  191 +// @override
  192 +// bool add(E value) {
  193 +// final val = _value.add(value);
  194 +// refresh();
  195 +// return val;
  196 +// }
  197 +
  198 +// @override
  199 +// void addAll(Iterable<E> item) {
  200 +// _value.addAll(item);
  201 +// refresh();
  202 +// }
  203 +
  204 +// /// Adds only if [item] is not null.
  205 +// void addNonNull(E item) {
  206 +// if (item != null) add(item);
  207 +// }
  208 +
  209 +// /// Adds only if [item] is not null.
  210 +// void addAllNonNull(Iterable<E> item) {
  211 +// if (item != null) addAll(item);
  212 +// }
  213 +
  214 +// int get length => value.length;
  215 +
  216 +// /// Removes an item from the list.
  217 +// ///
  218 +// /// This is O(N) in the number of items in the list.
  219 +// ///
  220 +// /// Returns whether the item was present in the list.
  221 +// bool remove(Object item) {
  222 +// var hasRemoved = _value.remove(item);
  223 +// if (hasRemoved) {
  224 +// refresh();
  225 +// }
  226 +// return hasRemoved;
  227 +// }
  228 +
  229 +// void removeWhere(bool Function(E) test) {
  230 +// _value.removeWhere(test);
  231 +// refresh();
  232 +// }
  233 +
  234 +// void clear() {
  235 +// _value.clear();
  236 +// refresh();
  237 +// }
  238 +
  239 +// void close() {
  240 +// _subscriptions.forEach((observable, subscription) {
  241 +// subscription.cancel();
  242 +// });
  243 +// _subscriptions.clear();
  244 +// subject.close();
  245 +// }
  246 +
  247 +// /// Replaces all existing items of this list with [item]
  248 +// void assign(E item) {
  249 +// clear();
  250 +// add(item);
  251 +// }
  252 +
  253 +// void update(void fn(Iterable<E> value)) {
  254 +// fn(value);
  255 +// refresh();
  256 +// }
  257 +
  258 +// /// Replaces all existing items of this list with [items]
  259 +// void assignAll(Iterable<E> items) {
  260 +// clear();
  261 +// addAll(items);
  262 +// }
  263 +
  264 +// @protected
  265 +// Set<E> get value {
  266 +// if (getObs != null) {
  267 +// getObs.addListener(subject.stream);
  268 +// }
  269 +// return _value;
  270 +// }
  271 +
  272 +// String get string => value.toString();
  273 +
  274 +// void addListener(Stream<Set<E>> rxGetX) {
  275 +// if (_subscriptions.containsKey(rxGetX)) {
  276 +// return;
  277 +// }
  278 +// _subscriptions[rxGetX] = rxGetX.listen((data) {
  279 +// subject.add(data);
  280 +// });
  281 +// }
  282 +
  283 +// set value(Set<E> val) {
  284 +// if (_value == val) return;
  285 +// _value = val;
  286 +// refresh();
  287 +// }
  288 +
  289 +// Stream<Set<E>> get stream => subject.stream;
  290 +
  291 +// StreamSubscription<Set<E>> listen(void Function(Set<E>) onData,
  292 +// {Function onError, void Function() onDone, bool cancelOnError}) =>
  293 +// stream.listen(onData, onError: onError, onDone: onDone);
  294 +
  295 +// /// Binds an existing [Stream<Set>] to this [RxSet].
  296 +// /// You can bind multiple sources to update the value.
  297 +// /// Closing the subscription will happen automatically when the observer
  298 +// /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.
  299 +// void bindStream(Stream<Set<E>> stream) {
  300 +// _subscriptions[stream] = stream.listen((va) => value = va);
  301 +// }
  302 +
  303 +// @override
  304 +// E get first => value.first;
  305 +
  306 +// @override
  307 +// E get last => value.last;
  308 +
  309 +// @override
  310 +// bool any(bool Function(E) test) {
  311 +// return value.any(test);
  312 +// }
  313 +
  314 +// @override
  315 +// Set<R> cast<R>() {
  316 +// return value.cast<R>();
  317 +// }
  318 +
  319 +// @override
  320 +// bool contains(Object element) {
  321 +// return value.contains(element);
  322 +// }
  323 +
  324 +// @override
  325 +// E elementAt(int index) {
  326 +// return value.elementAt(index);
  327 +// }
  328 +
  329 +// @override
  330 +// bool every(bool Function(E) test) {
  331 +// return value.every(test);
  332 +// }
  333 +
  334 +// @override
  335 +// Iterable<T> expand<T>(Iterable<T> Function(E) f) {
  336 +// return value.expand(f);
  337 +// }
  338 +
  339 +// @override
  340 +// E firstWhere(bool Function(E) test, {E Function() orElse}) {
  341 +// return value.firstWhere(test, orElse: orElse);
  342 +// }
  343 +
  344 +// @override
  345 +// T fold<T>(T initialValue, T Function(T, E) combine) {
  346 +// return value.fold(initialValue, combine);
  347 +// }
  348 +
  349 +// @override
  350 +// Iterable<E> followedBy(Iterable<E> other) {
  351 +// return value.followedBy(other);
  352 +// }
  353 +
  354 +// @override
  355 +// void forEach(void Function(E) f) {
  356 +// value.forEach(f);
  357 +// }
  358 +
  359 +// @override
  360 +// String join([String separator = ""]) {
  361 +// return value.join(separator);
  362 +// }
  363 +
  364 +// @override
  365 +// E lastWhere(bool Function(E) test, {E Function() orElse}) {
  366 +// return value.lastWhere(test, orElse: orElse);
  367 +// }
  368 +
  369 +// @override
  370 +// Iterable<T> map<T>(T Function(E) f) {
  371 +// return value.map(f);
  372 +// }
  373 +
  374 +// @override
  375 +// E reduce(E Function(E, E) combine) {
  376 +// return value.reduce(combine);
  377 +// }
  378 +
  379 +// @override
  380 +// E get single => value.single;
  381 +
  382 +// @override
  383 +// E singleWhere(bool Function(E) test, {E Function() orElse}) {
  384 +// return value.singleWhere(test, orElse: orElse);
  385 +// }
  386 +
  387 +// @override
  388 +// Iterable<E> skip(int count) {
  389 +// return value.skip(count);
  390 +// }
  391 +
  392 +// @override
  393 +// Iterable<E> skipWhile(bool Function(E) test) {
  394 +// return value.skipWhile(test);
  395 +// }
  396 +
  397 +// @override
  398 +// Iterable<E> take(int count) {
  399 +// return value.take(count);
  400 +// }
  401 +
  402 +// @override
  403 +// Iterable<E> takeWhile(bool Function(E) test) {
  404 +// return value.takeWhile(test);
  405 +// }
  406 +
  407 +// @override
  408 +// List<E> toList({bool growable = true}) {
  409 +// return value.toList(growable: growable);
  410 +// }
  411 +
  412 +// @override
  413 +// Set<E> toSet() {
  414 +// return value.toSet();
  415 +// }
  416 +
  417 +// @override
  418 +// Iterable<E> where(bool Function(E) test) {
  419 +// return value.where(test);
  420 +// }
  421 +
  422 +// @override
  423 +// Iterable<T> whereType<T>() {
  424 +// return value.whereType<T>();
  425 +// }
  426 +
  427 +// @override
  428 +// bool containsAll(Iterable<Object> other) {
  429 +// return value.containsAll(other);
  430 +// }
  431 +
  432 +// @override
  433 +// Set<E> difference(Set<Object> other) {
  434 +// return value.difference(other);
  435 +// }
  436 +
  437 +// @override
  438 +// Set<E> intersection(Set<Object> other) {
  439 +// return value.intersection(other);
  440 +// }
  441 +
  442 +// @override
  443 +// E lookup(Object object) {
  444 +// return value.lookup(object);
  445 +// }
  446 +
  447 +// @override
  448 +// void removeAll(Iterable<Object> elements) {
  449 +// _value.removeAll(elements);
  450 +// refresh();
  451 +// }
  452 +
  453 +// @override
  454 +// void retainAll(Iterable<Object> elements) {
  455 +// _value.retainAll(elements);
  456 +// refresh();
  457 +// }
  458 +
  459 +// @override
  460 +// void retainWhere(bool Function(E) E) {
  461 +// _value.retainWhere(E);
  462 +// refresh();
  463 +// }
  464 +
  465 +// @override
  466 +// Set<E> union(Set<E> other) {
  467 +// return value.union(other);
  468 +// }
  469 +// }
  470 +
  471 +extension SetExtension<E> on Set<E> {
  472 + RxSet<E> get obs {
  473 + if (this != null) {
  474 + return RxSet<E>(<E>{})..addAllNonNull(this);
  475 + } else {
  476 + return RxSet<E>(null);
  477 + }
  478 + }
  479 +}
  1 +library rx_types;
  2 +
  3 +import 'dart:async';
  4 +import 'dart:collection';
  5 +
  6 +import 'package:flutter/foundation.dart';
  7 +import '../rx_stream/rx_stream.dart';
  8 +import '../rx_typedefs/rx_typedefs.dart';
  9 +
  10 +part 'rx_core/rx_impl.dart';
  11 +part 'rx_core/rx_interface.dart';
  12 +part 'rx_core/rx_num.dart';
  13 +
  14 +part 'rx_iterables/rx_list.dart';
  15 +part 'rx_iterables/rx_set.dart';
  16 +part 'rx_iterables/rx_map.dart';
1 import 'dart:async'; 1 import 'dart:async';
  2 +
2 import '../../../get_core/get_core.dart'; 3 import '../../../get_core/get_core.dart';
3 -import '../rx_core/rx_interface.dart'; 4 +import '../rx_types/rx_types.dart';
4 import 'utils/debouncer.dart'; 5 import 'utils/debouncer.dart';
5 6
6 bool _conditional(dynamic condition) { 7 bool _conditional(dynamic condition) {
@@ -42,7 +43,7 @@ bool _conditional(dynamic condition) { @@ -42,7 +43,7 @@ bool _conditional(dynamic condition) {
42 /// ``` 43 /// ```
43 Worker ever<T>(RxInterface<T> listener, Function(T) callback, 44 Worker ever<T>(RxInterface<T> listener, Function(T) callback,
44 {dynamic condition = true}) { 45 {dynamic condition = true}) {
45 - StreamSubscription sub = listener.subject.stream.listen((event) { 46 + StreamSubscription sub = listener.subject.listen((event) {
46 if (_conditional(condition)) callback(event); 47 if (_conditional(condition)) callback(event);
47 }); 48 });
48 return Worker(sub.cancel, '[ever]'); 49 return Worker(sub.cancel, '[ever]');
@@ -56,7 +57,7 @@ Worker everAll(List<RxInterface> listeners, Function(dynamic) callback, @@ -56,7 +57,7 @@ Worker everAll(List<RxInterface> listeners, Function(dynamic) callback,
56 {dynamic condition = true}) { 57 {dynamic condition = true}) {
57 final evers = <StreamSubscription>[]; 58 final evers = <StreamSubscription>[];
58 for (var i in listeners) { 59 for (var i in listeners) {
59 - final sub = i.subject.stream.listen((event) { 60 + final sub = i.subject.listen((event) {
60 if (_conditional(condition)) callback(event); 61 if (_conditional(condition)) callback(event);
61 }); 62 });
62 evers.add(sub); 63 evers.add(sub);
@@ -97,7 +98,7 @@ Worker once<T>(RxInterface<T> listener, Function(T) callback, @@ -97,7 +98,7 @@ Worker once<T>(RxInterface<T> listener, Function(T) callback,
97 {dynamic condition}) { 98 {dynamic condition}) {
98 Worker ref; 99 Worker ref;
99 StreamSubscription sub; 100 StreamSubscription sub;
100 - sub = listener.subject.stream.listen((event) { 101 + sub = listener.subject.listen((event) {
101 if (!_conditional(condition)) return; 102 if (!_conditional(condition)) return;
102 ref._disposed = true; 103 ref._disposed = true;
103 ref._log('called'); 104 ref._log('called');
@@ -129,7 +130,7 @@ Worker interval<T>(RxInterface<T> listener, Function(T) callback, @@ -129,7 +130,7 @@ Worker interval<T>(RxInterface<T> listener, Function(T) callback,
129 {Duration time = const Duration(seconds: 1), dynamic condition = true}) { 130 {Duration time = const Duration(seconds: 1), dynamic condition = true}) {
130 var debounceActive = false; 131 var debounceActive = false;
131 time ??= const Duration(seconds: 1); 132 time ??= const Duration(seconds: 1);
132 - StreamSubscription sub = listener.subject.stream.listen((event) async { 133 + StreamSubscription sub = listener.subject.listen((event) async {
133 if (debounceActive || !_conditional(condition)) return; 134 if (debounceActive || !_conditional(condition)) return;
134 debounceActive = true; 135 debounceActive = true;
135 await Future.delayed(time); 136 await Future.delayed(time);
@@ -162,7 +163,7 @@ Worker debounce<T>(RxInterface<T> listener, Function(T) callback, @@ -162,7 +163,7 @@ Worker debounce<T>(RxInterface<T> listener, Function(T) callback,
162 {Duration time}) { 163 {Duration time}) {
163 final _debouncer = 164 final _debouncer =
164 Debouncer(delay: time ?? const Duration(milliseconds: 800)); 165 Debouncer(delay: time ?? const Duration(milliseconds: 800));
165 - StreamSubscription sub = listener.subject.stream.listen((event) { 166 + StreamSubscription sub = listener.subject.listen((event) {
166 _debouncer(() { 167 _debouncer(() {
167 callback(event); 168 callback(event);
168 }); 169 });
@@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart';
4 4
5 import '../../../get_core/get_core.dart'; 5 import '../../../get_core/get_core.dart';
6 import '../../../get_instance/src/get_instance.dart'; 6 import '../../../get_instance/src/get_instance.dart';
7 -import '../../../get_rx/get_rx.dart'; 7 +import '../../../get_rx/src/rx_types/rx_types.dart';
8 import '../../get_state_manager.dart'; 8 import '../../get_state_manager.dart';
9 9
10 typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function( 10 typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function(
@@ -38,10 +38,11 @@ class GetX<T extends DisposableInterface> extends StatefulWidget { @@ -38,10 +38,11 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
38 // this.streamController 38 // this.streamController
39 }); 39 });
40 40
41 - GetImplXState<T> createState() => GetImplXState<T>(); 41 + @override
  42 + GetXState<T> createState() => GetXState<T>();
42 } 43 }
43 44
44 -class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> { 45 +class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
45 RxInterface _observer; 46 RxInterface _observer;
46 T controller; 47 T controller;
47 bool isCreator = false; 48 bool isCreator = false;
@@ -76,7 +77,7 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> { @@ -76,7 +77,7 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
76 if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) { 77 if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) {
77 controller?.onStart(); 78 controller?.onStart();
78 } 79 }
79 - subs = _observer.subject.stream.listen((data) => setState(() {})); 80 + subs = _observer.subject.listen((data) => setState(() {}));
80 super.initState(); 81 super.initState();
81 } 82 }
82 83
1 import 'dart:async'; 1 import 'dart:async';
2 import 'package:flutter/widgets.dart'; 2 import 'package:flutter/widgets.dart';
3 -import '../../../get_rx/get_rx.dart'; 3 +import '../../../get_rx/src/rx_types/rx_types.dart';
4 4
5 typedef WidgetCallback = Widget Function(); 5 typedef WidgetCallback = Widget Function();
6 6
@@ -12,6 +12,7 @@ typedef WidgetCallback = Widget Function(); @@ -12,6 +12,7 @@ typedef WidgetCallback = Widget Function();
12 abstract class ObxWidget extends StatefulWidget { 12 abstract class ObxWidget extends StatefulWidget {
13 const ObxWidget({Key key}) : super(key: key); 13 const ObxWidget({Key key}) : super(key: key);
14 14
  15 + @override
15 _ObxState createState() => _ObxState(); 16 _ObxState createState() => _ObxState();
16 17
17 @protected 18 @protected
@@ -28,7 +29,7 @@ class _ObxState extends State<ObxWidget> { @@ -28,7 +29,7 @@ class _ObxState extends State<ObxWidget> {
28 29
29 @override 30 @override
30 void initState() { 31 void initState() {
31 - subs = _observer.subject.stream.listen((data) => setState(() {})); 32 + subs = _observer.subject.listen((data) => setState(() {}));
32 super.initState(); 33 super.initState();
33 } 34 }
34 35
@@ -21,5 +21,6 @@ import '../../get_state_manager.dart'; @@ -21,5 +21,6 @@ import '../../get_state_manager.dart';
21 /// ``` 21 /// ```
22 mixin SingleGetTickerProviderMixin on DisposableInterface 22 mixin SingleGetTickerProviderMixin on DisposableInterface
23 implements TickerProvider { 23 implements TickerProvider {
  24 + @override
24 Ticker createTicker(TickerCallback onTick) => Ticker(onTick); 25 Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
25 } 26 }
1 import 'dart:async'; 1 import 'dart:async';
2 -  
3 import 'package:flutter/foundation.dart'; 2 import 'package:flutter/foundation.dart';
4 import 'package:flutter_test/flutter_test.dart'; 3 import 'package:flutter_test/flutter_test.dart';
5 import 'package:get/state_manager.dart'; 4 import 'package:get/state_manager.dart';
@@ -7,8 +6,8 @@ import 'package:get/state_manager.dart'; @@ -7,8 +6,8 @@ import 'package:get/state_manager.dart';
7 int times = 3; 6 int times = 3;
8 int get last => times - 1; 7 int get last => times - 1;
9 8
10 -Future<String> valueNotifier() {  
11 - final c = Completer<String>(); 9 +Future<int> valueNotifier() {
  10 + final c = Completer<int>();
12 final value = ValueNotifier<int>(0); 11 final value = ValueNotifier<int>(0);
13 final timer = Stopwatch(); 12 final timer = Stopwatch();
14 timer.start(); 13 timer.start();
@@ -16,8 +15,9 @@ Future<String> valueNotifier() { @@ -16,8 +15,9 @@ Future<String> valueNotifier() {
16 value.addListener(() { 15 value.addListener(() {
17 if (last == value.value) { 16 if (last == value.value) {
18 timer.stop(); 17 timer.stop();
19 - c.complete(  
20 - """${value.value} listeners notified | [VALUENOTIFIER] objs time: ${timer.elapsedMicroseconds}ms"""); 18 + print(
  19 + """${value.value} listeners notified | [VALUE_NOTIFIER] time: ${timer.elapsedMicroseconds}ms""");
  20 + c.complete(timer.elapsedMicroseconds);
21 } 21 }
22 }); 22 });
23 23
@@ -28,8 +28,8 @@ Future<String> valueNotifier() { @@ -28,8 +28,8 @@ Future<String> valueNotifier() {
28 return c.future; 28 return c.future;
29 } 29 }
30 30
31 -Future<String> getValue() {  
32 - final c = Completer<String>(); 31 +Future<int> getValue() {
  32 + final c = Completer<int>();
33 final value = Value<int>(0); 33 final value = Value<int>(0);
34 final timer = Stopwatch(); 34 final timer = Stopwatch();
35 timer.start(); 35 timer.start();
@@ -37,8 +37,9 @@ Future<String> getValue() { @@ -37,8 +37,9 @@ Future<String> getValue() {
37 value.addListener(() { 37 value.addListener(() {
38 if (last == value.value) { 38 if (last == value.value) {
39 timer.stop(); 39 timer.stop();
40 - c.complete(  
41 - """${value.value} listeners notified | [GETX VALUE] objs time: ${timer.elapsedMicroseconds}ms"""); 40 + print(
  41 + """${value.value} listeners notified | [GETX_VALUE] time: ${timer.elapsedMicroseconds}ms""");
  42 + c.complete(timer.elapsedMicroseconds);
42 } 43 }
43 }); 44 });
44 45
@@ -49,8 +50,8 @@ Future<String> getValue() { @@ -49,8 +50,8 @@ Future<String> getValue() {
49 return c.future; 50 return c.future;
50 } 51 }
51 52
52 -Future<String> getStream() {  
53 - final c = Completer<String>(); 53 +Future<int> stream() {
  54 + final c = Completer<int>();
54 55
55 final value = StreamController<int>(); 56 final value = StreamController<int>();
56 final timer = Stopwatch(); 57 final timer = Stopwatch();
@@ -59,8 +60,55 @@ Future<String> getStream() { @@ -59,8 +60,55 @@ Future<String> getStream() {
59 value.stream.listen((v) { 60 value.stream.listen((v) {
60 if (last == v) { 61 if (last == v) {
61 timer.stop(); 62 timer.stop();
62 - c.complete(  
63 - """$v listeners notified | [STREAM] objs time: ${timer.elapsedMicroseconds}ms"""); 63 + print(
  64 + """$v listeners notified | [STREAM] time: ${timer.elapsedMicroseconds}ms""");
  65 + c.complete(timer.elapsedMicroseconds);
  66 + }
  67 + });
  68 +
  69 + for (var i = 0; i < times; i++) {
  70 + value.add(i);
  71 + }
  72 +
  73 + return c.future;
  74 +}
  75 +
  76 +Future<int> getStream() {
  77 + final c = Completer<int>();
  78 +
  79 + final value = GetStream<int>();
  80 + final timer = Stopwatch();
  81 + timer.start();
  82 +
  83 + value.listen((v) {
  84 + if (last == v) {
  85 + timer.stop();
  86 + print(
  87 + """$v listeners notified | [GET_STREAM] time: ${timer.elapsedMicroseconds}ms""");
  88 + c.complete(timer.elapsedMicroseconds);
  89 + }
  90 + });
  91 +
  92 + for (var i = 0; i < times; i++) {
  93 + value.add(i);
  94 + }
  95 +
  96 + return c.future;
  97 +}
  98 +
  99 +Future<int> miniStream() {
  100 + final c = Completer<int>();
  101 +
  102 + final value = MiniStream<int>();
  103 + final timer = Stopwatch();
  104 + timer.start();
  105 +
  106 + value.listen((v) {
  107 + if (last == v) {
  108 + timer.stop();
  109 + print(
  110 + """$v listeners notified | [MINI_STREAM] time: ${timer.elapsedMicroseconds}ms""");
  111 + c.complete(timer.elapsedMicroseconds);
64 } 112 }
65 }); 113 });
66 114
@@ -72,15 +120,43 @@ Future<String> getStream() { @@ -72,15 +120,43 @@ Future<String> getStream() {
72 } 120 }
73 121
74 void main() async { 122 void main() async {
75 - test('run benchmarks', () async {  
76 - print(await getValue());  
77 - print(await valueNotifier());  
78 - print(await getStream()); 123 + test('run benchmarks from ValueNotifier', () async {
  124 + await getValue();
  125 + await valueNotifier();
  126 +
  127 + times = 30000;
  128 + await getValue();
  129 + await valueNotifier();
  130 + });
  131 +
  132 + test('percentage test', () {
  133 + final referenceValue = 200;
  134 + final requestedValue = 100;
  135 +
  136 + print('''
  137 +referenceValue is ${calculePercentage(referenceValue, requestedValue)}% more than requestedValue''');
  138 + expect(calculePercentage(referenceValue, requestedValue), 100);
  139 + });
  140 +
  141 + test('run benchmarks from Streams', () async {
  142 + var dart = await stream();
  143 + var getx = await getStream();
  144 + var mini = await miniStream();
  145 + print('''
  146 +GetStream is ${calculePercentage(dart, getx).round()}% more fast than Default Stream with $last listeners''');
79 times = 30000; 147 times = 30000;
80 - print(await getValue());  
81 - print(await valueNotifier());  
82 - print(await getStream()); 148 + dart = await stream();
  149 + getx = await getStream();
  150 + mini = await miniStream();
  151 +
  152 + print('dart is $dart');
  153 + print('getx is $getx');
  154 + print('mini is $mini');
  155 + print('''
  156 +GetStream is ${calculePercentage(dart, getx).round()}% more fast than Default Stream with $last listeners''');
83 }); 157 });
84 } 158 }
85 159
86 -typedef VoidCallback = void Function(); 160 +int calculePercentage(int dart, int getx) {
  161 + return (dart / getx * 100).round() - 100;
  162 +}