diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..b4d6e266
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,64 @@
+# Created by .ignore support plugin (hsz.mobi)
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff:
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/dictionaries
+
+# Sensitive or high-churn files:
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.xml
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+
+# Gradle:
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# CMake
+cmake-build-debug/
+
+# Mongo Explorer plugin:
+.idea/**/mongoSettings.xml
+
+## File-based project format:
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+### Dart template
+# See https://www.dartlang.org/tools/private-files.html
+
+# Files and directories created by pub
+.packages
+.pub/
+build/
+# If you're building an application, you may want to check-in your pubspec.lock
+pubspec.lock
+
+# Directory created by dartdoc
+# If you don't generate documentation locally you can remove this line.
+doc/api/
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..639900d1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..f6374af3
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 00000000..518eb901
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,2 @@
+analyzer:
+ strong-mode: true
\ No newline at end of file
diff --git a/lib/angel_poll.dart b/lib/angel_poll.dart
new file mode 100644
index 00000000..5e30caa4
--- /dev/null
+++ b/lib/angel_poll.dart
@@ -0,0 +1,93 @@
+import 'dart:async';
+import 'package:angel_client/angel_client.dart';
+
+class Poll extends Service {
+ final Service inner;
+
+ final String idField;
+ final bool asPaginated;
+
+ final List _items = [];
+ final StreamController _onIndexed = new StreamController(),
+ _onRead = new StreamController(),
+ _onCreated = new StreamController(),
+ _onModified = new StreamController(),
+ _onUpdated = new StreamController(),
+ _onRemoved = new StreamController();
+
+ bool Function(dynamic, dynamic) _compare;
+ Timer _timer;
+
+ @override
+ Angel get app => inner.app;
+
+ @override
+ Stream get onIndexed => _onIndexed.stream;
+
+ @override
+ Stream get onRead => _onRead.stream;
+
+ @override
+ Stream get onCreated => _onCreated.stream;
+
+ @override
+ Stream get onModified => _onModified.stream;
+
+ @override
+ Stream get onUpdated => _onUpdated.stream;
+
+ @override
+ Stream get onRemoved => _onRemoved.stream;
+
+ Poll(this.inner, Duration interval,
+ {this.idField: 'id', this.asPaginated: false, bool compare(a, b)}) {
+ _timer = new Timer.periodic(interval, _timerCallback);
+ _compare = compare ?? (a, b) => a[idField ?? 'id'] == b[idField ?? 'id'];
+ }
+
+ @override
+ Future close() async {
+ _timer.cancel();
+ _onIndexed.close();
+ _onRead.close();
+ _onCreated.close();
+ _onModified.close();
+ _onUpdated.close();
+ _onRemoved.close();
+ }
+
+ @override
+ Future index([Map params]) {
+ return inner.index().then((data) {
+ var items = asPaginated == true ? data['data'] : data;
+ _items
+ ..clear()
+ ..addAll(items);
+ _onIndexed.add(items);
+ });
+ }
+
+ @override
+ Future remove(id, [Map params]) {}
+
+ @override
+ Future update(id, data, [Map params]) {}
+
+ @override
+ Future modify(id, data, [Map params]) {}
+
+ @override
+ Future create(data, [Map params]) {}
+
+ @override
+ Future read(id, [Map params]) {}
+
+ void _timerCallback(Timer timer) {
+ index().then((data) {
+ var items = asPaginated == true ? data['data'] : data;
+
+ // TODO: Check create, modify, remove
+
+ }).catchError(_onIndexed.addError);
+ }
+}
diff --git a/poll.iml b/poll.iml
new file mode 100644
index 00000000..5a5ced28
--- /dev/null
+++ b/poll.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 00000000..5b9b9034
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,6 @@
+name: angel_poll
+dependencies:
+ angel_client: ^1.0.0
+dev_dependencies:
+ angel_test: ^1.1.0
+ test: ^0.12.0
\ No newline at end of file