├── .gitignore
├── HOWTO.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── coshx
│ │ └── drekkartest
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── coshx
│ │ │ └── drekkartest
│ │ │ ├── BasicTriggeringActivity.java
│ │ │ ├── BenchmarkActivity.java
│ │ │ ├── EventDataActivity.java
│ │ │ ├── EventNameActivity.java
│ │ │ ├── InitializationActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MultipleSubscriberActivity.java
│ │ │ ├── ThreadingActivity.java
│ │ │ ├── TwoBucketActivity.java
│ │ │ ├── TwoBusActivity.java
│ │ │ ├── TwoEventActivity.java
│ │ │ ├── UnregistrationActivity.java
│ │ │ └── WebActivity.java
│ └── res
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── two_buckets.xml
│ │ └── webview_layout.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── raw
│ │ ├── basic_triggering.js
│ │ ├── basic_triggering_page.html
│ │ ├── benchmark.js
│ │ ├── benchmark_page.html
│ │ ├── event_data.js
│ │ ├── event_data_page.html
│ │ ├── event_name.js
│ │ ├── event_name_page.html
│ │ ├── initialization.js
│ │ ├── initialization_page.html
│ │ ├── multiple_subscribers.js
│ │ ├── multiple_subscribers_page.html
│ │ ├── threading.js
│ │ ├── threading_page.html
│ │ ├── two_buckets.js
│ │ ├── two_buckets_page.html
│ │ ├── two_buses.js
│ │ ├── two_buses_page.html
│ │ ├── two_events.js
│ │ ├── two_events_page.html
│ │ ├── unregistration.js
│ │ └── unregistration_page.html
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── coshx
│ └── drekkartest
│ └── ExampleUnitTest.java
├── build.gradle
├── drekkar.iml
├── drekkar
├── .gitignore
├── build.gradle
├── drekkar-drekkar.iml
├── drekkar.iml
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── coshx
│ │ └── drekkar
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── coshx
│ │ │ └── drekkar
│ │ │ ├── Arguments.java
│ │ │ ├── Callback.java
│ │ │ ├── DataSerializer.java
│ │ │ ├── Drekkar.java
│ │ │ ├── DrekkarFactory.java
│ │ │ ├── EventBus.java
│ │ │ ├── EventSubscriber.java
│ │ │ ├── IWebViewJSEndpoint.java
│ │ │ ├── ThreadingHelper.java
│ │ │ ├── WebViewJSEndpoint.java
│ │ │ ├── WebViewJSEndpointMediator.java
│ │ │ ├── WhenReady.java
│ │ │ └── WhenReadyOnMain.java
│ └── res
│ │ ├── raw
│ │ ├── drekkar.js
│ │ └── drekkar_min.js
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── coshx
│ └── drekkar
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── js
├── Gruntfile.js
├── coffeelint-config.json
├── drekkar.coffee
└── package.json
├── logo.png
├── original_logo.png
├── settings.gradle
└── src.iml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | /*/build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Tmp
30 | .DS_Store
31 | *~
32 | *.map
33 |
34 | .idea
35 | js/node_modules
36 | javadoc/
--------------------------------------------------------------------------------
/HOWTO.md:
--------------------------------------------------------------------------------
1 | # HOW TO
2 |
3 | ## Publish a new release
4 |
5 | 1. Apply any needed change
6 | 1. Increment the version number into the Gruntfile
7 | 1. Run both `default` and `release` target to build the scripts
8 | 1. Increment the version number into the Readme, install section (gradle has to match the latest tag)
9 | 1. Push your changes and create a new tag. The new tag has to be created before pushing the lib.
10 | 1. From the root folder, run this command to update the lib (and pushing to JitPack):
11 |
12 | ```./gradlew install```
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Coshx Labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](https://jitpack.io/#coshx/drekkar)
4 |
5 | [](https://gitter.im/coshx/drekkar?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 |
7 | **An event bus for sending messages between WebView and embedded JS. [Alter ego of Caravel](https://github.com/coshx/caravel).**
8 |
9 | ## Features
10 |
11 | * Easy, fast and reliable event bus system
12 | * Multiple bus support
13 | * Multithreading support
14 | * WebView ~> JavaScript supported types:
15 | - `Bool`
16 | - `Int`
17 | - `Float`
18 | - `Double`
19 | - `String`
20 | - Any list (using types in this list, including maps)
21 | - Any map (using types in this list, including lists)
22 | * JavaScript ~> Android supported types:
23 | - `Boolean`
24 | - `Int`
25 | - `Float` (available as a `Double`)
26 | - `String`
27 | - `Array` (available as a `List`)
28 | - `Object` (available as a `Map`)
29 |
30 | ## Installation
31 |
32 | ### Using JitPack
33 |
34 | Merge this code into your root build.gradle file:
35 |
36 | ```groovy
37 | allprojects {
38 | repositories {
39 | maven { url "https://jitpack.io" }
40 | }
41 | }
42 | ```
43 |
44 | Then, add this dependency to your module:
45 |
46 | ```groovy
47 | dependencies {
48 | compile 'com.github.coshx:drekkar:v0.1.1'
49 | }
50 | ```
51 |
52 | Finally, you need to load the internal JS script Drekkar is using to make magic happen. You can either use `R.draw.drekkar_min` or add the minified JS script from [the latest release](https://github.com/coshx/drekkar/releases) to your `raw` resources. This script must be loaded in any webpage you are using Drekkar.
53 |
54 | ### Using as a submodule
55 |
56 | Clone this repo and add the `drekkar` module to your workspace.
57 |
58 | ## Get started
59 |
60 | Drekkar allows developers to communicate between their `WebView` and the embedded JS. You can send any kind of message between these two folks.
61 |
62 | Have a glance at this super simple sample. Let's start with the Android part:
63 |
64 | ```java
65 | class MyActivity extends Activity {
66 | WebView webView;
67 |
68 | void onCreate(Bundle savedInstanceState) {
69 | super.onCreate(savedInstanceState);
70 |
71 | webView = (WebView) findViewById(R.id.my_webview_id);
72 |
73 | // Prepare your bus before loading your web view's content
74 | Drekkar.getDefault(this, webView, new WhenReady() {
75 | @Override
76 | public void run(EventBus bus) {
77 | // In this scope, the JS endpoint is ready to handle any event.
78 | // Register and post your events here
79 | List list = new ArrayList<>();
80 | list.add(1);
81 | list.add(2);
82 | list.add(3);
83 |
84 | bus.post("MyEvent", list);
85 |
86 | MyActivity.this.bus = bus; // You can save your bus for firing events later
87 | }
88 | });
89 |
90 | // ... Load web view's content there
91 | }
92 | }
93 | ```
94 |
95 | And now, in your JS:
96 |
97 | ```javascript
98 | var bus = Drekkar.getDefault();
99 |
100 | bus.register("AnEventWithAString", function(name, data) {
101 | alert('I received this string: ' + data);
102 | bus.post("AnEventForAndroid");
103 | });
104 | ```
105 |
106 | And voilà!
107 |
108 | ## Porting your app from Caravel to Drekkar
109 |
110 | Super duper easy. Just use the same codebase and use the JS script from Drekkar. Finally, add this after having loaded the Drekkar script:
111 |
112 | ```javascript
113 | var Caravel = Drekkar;
114 | ```
115 |
116 | ## Troubleshooting
117 |
118 | ### 😕 Sometimes the bus is not working?!
119 |
120 | Firstly, ensure you are using the bus correctly. Check if you are unregistering the bus when exiting the controller owning your web component. Use the [unregister method for this]().
121 |
122 | Drekkar automatically cleans up any unused bus when you create a new one. However, this operation is run in the background to avoid any delay on your side. So, a thread collision might happen if you have not unsubscribed your bus properly.
123 |
124 | However, if you think everything is good with your codebase, feel free to open a ticket.
125 |
126 | ### What object should I use as a subscriber?
127 |
128 | A subscriber could be any object **except the watched target**. We recommend to use the activity/current context as a subscriber (it is a common pattern).
129 |
130 | ### Reserved names
131 |
132 | `DrekkarInit` is an internal event, sent by the JS part for running the `WhenReady` object.
133 |
134 | Also, the default bus is named `default`. If you use this name for a custom bus, Drekkar will automatically switch to the default one.
135 |
136 | Finally, Drekkar names its JS interface `DrekkarWebViewJSEndpoint`.
137 |
138 | ### Keep in mind event and bus names are case-sensitive.
139 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.coshx.drekkartest"
9 | minSdkVersion 15
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:22.2.1'
26 | compile 'com.android.support:design:22.2.1'
27 | compile project(':drekkar')
28 | }
29 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/acadet/android-sdks/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/coshx/drekkartest/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkartest;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/coshx/drekkartest/BasicTriggeringActivity.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkartest;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.coshx.drekkar.Callback;
6 | import com.coshx.drekkar.Drekkar;
7 | import com.coshx.drekkar.EventBus;
8 | import com.coshx.drekkar.WhenReady;
9 |
10 | /**
11 | * @class BasicTriggeringActivity
12 | * @brief
13 | */
14 | public class BasicTriggeringActivity extends WebActivity {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 |
20 | Drekkar.getDefault(
21 | this, webView, new WhenReady() {
22 | @Override
23 | public void run(final EventBus bus) {
24 | bus.register(
25 | "From JS", new Callback() {
26 | @Override
27 | public void run(String name, Object data) {
28 | bus.post("From Android");
29 | }
30 | }
31 | );
32 | }
33 | }
34 | );
35 |
36 | loadURL("basic_triggering");
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/coshx/drekkartest/BenchmarkActivity.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkartest;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.coshx.drekkar.Callback;
6 | import com.coshx.drekkar.Drekkar;
7 | import com.coshx.drekkar.EventBus;
8 | import com.coshx.drekkar.WhenReady;
9 |
10 | import java.util.UUID;
11 |
12 | /**
13 | * @class BenchmarkActivity
14 | * @brief
15 | */
16 | public class BenchmarkActivity extends WebActivity {
17 |
18 | private EventBus bus;
19 |
20 | private void startTesting() {
21 | String name = UUID.randomUUID().toString();
22 |
23 | Drekkar.get(
24 | this, name, webView, new WhenReady() {
25 | @Override
26 | public void run(final EventBus bus) {
27 | for (int i = 0; i < 1000; i++) {
28 | bus.register(
29 | "Background-" + i, new Callback() {
30 | @Override
31 | public void run(String name, Object data) {
32 | bus.post(name + "-confirmation");
33 | }
34 | }
35 | );
36 |
37 | bus.registerOnMain(
38 | "Main-" + i, new Callback() {
39 | @Override
40 | public void run(String name, Object data) {
41 | bus.post(name + "-confirmation");
42 | }
43 | }
44 | );
45 | }
46 |
47 | bus.post("Ready");
48 | }
49 | }
50 | );
51 |
52 | bus.post("BusName", name);
53 | }
54 |
55 | @Override
56 | protected void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 |
59 | Drekkar.getDefault(
60 | this, webView, new WhenReady() {
61 | @Override
62 | public void run(EventBus bus) {
63 | BenchmarkActivity.this.bus = bus;
64 | bus.register(
65 | "Start", new Callback() {
66 | @Override
67 | public void run(String name, Object data) {
68 | startTesting();
69 | }
70 | }
71 | );
72 | }
73 | }
74 | );
75 |
76 | loadURL("benchmark");
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/coshx/drekkartest/EventDataActivity.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkartest;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 |
6 | import com.coshx.drekkar.Callback;
7 | import com.coshx.drekkar.Drekkar;
8 | import com.coshx.drekkar.EventBus;
9 | import com.coshx.drekkar.WhenReady;
10 |
11 | import java.util.ArrayList;
12 | import java.util.HashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | /**
17 | * @class EventDataActivity
18 | * @brief
19 | */
20 | public class EventDataActivity extends WebActivity {
21 |
22 | private void raise(String msg) {
23 | Log.e(EventDataActivity.class.getName(), msg);
24 | }
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 |
30 | Drekkar.getDefault(
31 | this, webView, new WhenReady() {
32 | @Override
33 | public void run(EventBus bus) {
34 | bus.post("Bool", true);
35 | bus.post("Int", 42);
36 | bus.post("Float", 19.92);
37 | bus.post("Double", 20.15);
38 | bus.post("String", "Churchill");
39 | bus.post("HazardousString", "There is a \" and a '");
40 |
41 | List list = new ArrayList<>();
42 | list.add(1);
43 | list.add(2);
44 | list.add(3);
45 | list.add(5);
46 | bus.post("List", list);
47 |
48 | Map dictionary = new HashMap();
49 | dictionary.put("foo", 45);
50 | dictionary.put("bar", 89);
51 | bus.post("Dictionary", dictionary);
52 |
53 | List
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/benchmark.js:
--------------------------------------------------------------------------------
1 | var sendBackgroundCounter = 0;
2 | var sendBackgroundCounterField = $('.js-send-background-counter');
3 | var receiveBackgroundCounter = 0;
4 | var receiveBackgroundCounterField = $('.js-receive-background-counter');
5 | var receiveBackgroundTimer = null;
6 | var receiveBackgroundTimerField = $('.js-receive-background-timer');
7 |
8 | var sendMainCounter = 0;
9 | var sendMainCounterField = $('.js-send-main-counter');
10 | var receiveMainCounter = 0;
11 | var receiveMainCounterField = $('.js-receive-main-counter');
12 | var receiveMainCounterTimer = null;
13 | var receiveMainCounterTimerField = $('.js-receive-main-timer');
14 |
15 | function append(msg) {
16 | $('body').append('' + msg + '
');
17 | }
18 |
19 | $('.js-start').on('click', function() {
20 | Drekkar.getDefault().post('Start');
21 | });
22 |
23 | Drekkar.getDefault().register("BusName", function(name, data) {
24 | var bus = Drekkar.get(data);
25 | var iterations = 1000;
26 |
27 | var postAction = function() {
28 | for (var i = 0; i < iterations; i++) {
29 | var captureIndex = (function(i) {
30 | setTimeout(
31 | function() {
32 | bus.post("Background-" + i);
33 | sendBackgroundCounter++;
34 | sendBackgroundCounterField.text(sendBackgroundCounter);
35 |
36 | bus.post("Main-" + i);
37 | sendMainCounter++;
38 | sendMainCounterField.text(sendMainCounter);
39 | },
40 | 0
41 | );
42 | })(i);
43 | }
44 | };
45 |
46 | append('Initializing...');
47 |
48 | for (var i = 0; i < iterations; i++) {
49 | var captureIndex = (function(i) {
50 | bus.register("Background-" + i + "-confirmation", function() {
51 | setTimeout(function() {
52 | receiveBackgroundCounter++;
53 | receiveBackgroundCounterField.text(receiveBackgroundCounter);
54 | if (receiveBackgroundCounter == iterations) {
55 | receiveBackgroundTimerField.text(Date.now() - receiveBackgroundTimer);
56 | }
57 | }, 0);
58 | });
59 |
60 | bus.register("Main-" + i + "-confirmation", function() {
61 | setTimeout(function() {
62 | receiveMainCounter++;
63 | receiveMainCounterField.text(receiveMainCounter);
64 | if (receiveMainCounter == iterations) {
65 | receiveMainCounterTimerField.text(Date.now() - receiveMainCounterTimer);
66 | }
67 | }, 0);
68 | });
69 | })(i);
70 | }
71 |
72 | bus.register("Ready", function() {
73 | append('Starting...');
74 | receiveBackgroundTimer = Date.now();
75 | receiveMainCounterTimer = Date.now();
76 | postAction();
77 | });
78 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/benchmark_page.html:
--------------------------------------------------------------------------------
1 | Benchmark
2 |
3 |
4 | Start
5 |
6 |
7 |
8 | Background:
9 |
10 | /
11 |
12 | /
13 |
14 |
15 |
16 |
17 | Main:
18 |
19 | /
20 |
21 | /
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/event_data.js:
--------------------------------------------------------------------------------
1 | function ok(name) {
2 | $('body').append('' + name + ' ok
');
3 | }
4 |
5 | function fail(name, data) {
6 | if ((data instanceof Array) || (data instanceof Object)) {
7 | data = JSON.stringify(data);
8 | }
9 | $('body').append('Failed for ' + name + ': received ' + data + '
');
10 | }
11 |
12 | Drekkar.getDefault().register("Bool", function(name, data) {
13 | if (data == true) {
14 | ok(name);
15 | } else {
16 | fail(name, data);
17 | }
18 | });
19 |
20 | Drekkar.getDefault().register("Int", function(name, data) {
21 | if (data == 42) {
22 | ok(name);
23 | } else {
24 | fail(name, data);
25 | }
26 | });
27 |
28 | Drekkar.getDefault().register("Float", function(name, data) {
29 | if (data.toFixed(2) == 19.92) {
30 | ok(name);
31 | } else {
32 | fail(name, data);
33 | }
34 | });
35 |
36 | Drekkar.getDefault().register("Double", function(name, data) {
37 | if (data == 20.15) {
38 | ok(name);
39 | } else {
40 | fail(name, data);
41 | }
42 | });
43 |
44 | Drekkar.getDefault().register("String", function(name, data) {
45 | if (data == "Churchill") {
46 | ok(name);
47 | } else {
48 | fail(name, data);
49 | }
50 | });
51 |
52 | Drekkar.getDefault().register("HazardousString", function(name, data) {
53 | if (data == "There is a \" and a '") {
54 | ok(name);
55 | } else {
56 | fail(name, data);
57 | }
58 | });
59 |
60 | Drekkar.getDefault().register("List", function(name, data) {
61 | if (JSON.stringify(data) == JSON.stringify([1, 2, 3, 5])) {
62 | ok(name);
63 | } else {
64 | fail(name, data);
65 | }
66 | });
67 |
68 | Drekkar.getDefault().register("Dictionary", function(name, data) {
69 | if (JSON.stringify(data) == JSON.stringify({ foo: 45, bar: 89 })) {
70 | ok(name);
71 | } else {
72 | fail(name, data);
73 | }
74 | });
75 |
76 | Drekkar.getDefault().register("ComplexArray", function(name, data) {
77 | var expectedData = [{name: "Alice", age: 24}, {name: "Bob", age: 23}];
78 | var customFail = function() {
79 | fail(name, data);
80 | };
81 |
82 | if (data.length == 2) {
83 | if (data[0].name == expectedData[0].name && data[0].age == expectedData[0].age) {
84 | if (data[1].name == expectedData[1].name && data[1].age == expectedData[1].age) {
85 | ok(name);
86 | } else {
87 | customFail();
88 | }
89 | } else {
90 | customFail();
91 | }
92 | } else {
93 | customFail();
94 | }
95 | });
96 |
97 | Drekkar.getDefault().register("ComplexDictionary", function(name, data) {
98 | var expectedData = {name: "Paul", address: { street: "Hugo", city: "Bordeaux" }, games:
99 | ["Fifa", "Star Wars"]};
100 | var customFail = function() {
101 | fail(name, data);
102 | };
103 |
104 | if (data.name == expectedData.name) {
105 | if (data.address.street == expectedData.address.street && data.address.city == expectedData.address.city) {
106 | if (data.games.length == expectedData.games.length && data.games[0] == expectedData.games[0] && data.games[1] == expectedData.games[1]) {
107 | ok(name);
108 | } else {
109 | customFail();
110 | }
111 | } else {
112 | customFail();
113 | }
114 | } else {
115 | customFail();
116 | }
117 | });
118 |
119 | Drekkar.getDefault().register("Ready", function() {
120 | Drekkar.getDefault().post("True", true);
121 | Drekkar.getDefault().post("False", false);
122 | Drekkar.getDefault().post("Int", 987);
123 | Drekkar.getDefault().post("Double", 15.15);
124 | Drekkar.getDefault().post("String", "Napoleon");
125 | Drekkar.getDefault().post("UUID", "9658ae60-9e0d-4da7-a63d-46fe75ff1db1");
126 | Drekkar.getDefault().post("Array", [3, 1, 4]);
127 | Drekkar.getDefault().post("Dictionary", { "movie": "Once upon a time in the West", "actor": "Charles Bronson" });
128 |
129 | Drekkar.getDefault().post("ComplexArray", [87, {"name": "Bruce Willis"}, "left-handed" ]);
130 | Drekkar.getDefault().post("ComplexDictionary", {name: "John Malkovich", movies: ["Dangerous Liaisons", "Burn after reading"], kids: 2});
131 | });
132 |
133 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/event_data_page.html:
--------------------------------------------------------------------------------
1 | Event data
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/event_name.js:
--------------------------------------------------------------------------------
1 | Drekkar.getDefault().register("Foo", function(name, data) {
2 | if (name == "Foo") {
3 | $('body').append('You should see me
');
4 | } else {
5 | $('body').append('You should not see me
');
6 | }
7 | });
8 |
9 | Drekkar.getDefault().register("Foobar", function(name, data) {
10 | $('body').append('You should not see me
');
11 | });
12 |
13 | Drekkar.getDefault().post('Bar');
--------------------------------------------------------------------------------
/app/src/main/res/raw/event_name_page.html:
--------------------------------------------------------------------------------
1 | Event name
2 |
3 | You should only see
You should see me
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/initialization.js:
--------------------------------------------------------------------------------
1 | Drekkar.getDefault().register("Before", function(name, data) {
2 | $('body').append('Before
');
3 | });
4 |
5 | Drekkar.getDefault().register("After", function(name, data) {
6 | $('body').append('After
');
7 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/initialization_page.html:
--------------------------------------------------------------------------------
1 | Initialization
2 |
3 | You should see
Before
After
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/multiple_subscribers.js:
--------------------------------------------------------------------------------
1 | Drekkar.getDefault().register("AnEvent", function(name, data) {
2 | $('body').append('First!
');
3 | });
4 |
5 | Drekkar.getDefault().register("AnEvent", function(name, data) {
6 | $('body').append('Second!
');
7 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/multiple_subscribers_page.html:
--------------------------------------------------------------------------------
1 | Multiple subscribers
2 |
3 | You should see:
First!
Second!
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/threading.js:
--------------------------------------------------------------------------------
1 | function append(msg) {
2 | $('body').append('' + msg + '
');
3 | }
4 |
5 | var firstBus = Drekkar.get("First");
6 | var secondBus = Drekkar.get("Second");
7 |
8 | secondBus.register("FromMain", function(name) {
9 | append(name);
10 | secondBus.post("FromJSForMain");
11 | });
12 |
13 | secondBus.register("FromMainAfterFromJS", function(name) {
14 | append(name);
15 | });
16 |
17 | firstBus.register("FromBackground", function(name) {
18 | append(name);
19 | firstBus.post("FromJSForBackground");
20 | })
21 |
22 | firstBus.register("FromBackgroundAfterFromJS", function(name) {
23 | append(name);
24 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/threading_page.html:
--------------------------------------------------------------------------------
1 | Threading
2 |
3 |
4 | You should see
5 |
FromMain
6 | FromBackground
7 | FromBackgroundAfterFromJS
8 | FromMainAfteromJS
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_buckets.js:
--------------------------------------------------------------------------------
1 | var bus = Drekkar.getDefault();
2 |
3 | bus.register("Foo", function() {
4 | $('body').append('Foo
');
5 | bus.post("Bar");
6 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_buckets_page.html:
--------------------------------------------------------------------------------
1 | Two buckets
2 |
3 | You should see
Foo
in upper part and below.
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_buses.js:
--------------------------------------------------------------------------------
1 | Drekkar.get("BarBus").register("AnEvent", function(name, data) {
2 | $('body').append('You should see me first and only once
');
3 | });
4 |
5 | Drekkar.get("FooBus").register("AnEvent", function(name, data) {
6 | $('body').append('You should see me after and only once
');
7 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_buses_page.html:
--------------------------------------------------------------------------------
1 | Two buses
2 |
3 | You should see
You should see me first and only once
You should see me after and only once
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_events.js:
--------------------------------------------------------------------------------
1 | Drekkar.getDefault().register("ThirdEvent", function(name, data) {
2 | $('body').append('You should see me and only me
');
3 | });
4 |
5 | Drekkar.getDefault().register("FourthEvent", function(name, data) {
6 | $('body').append('You should not see me
');
7 | });
8 |
9 | Drekkar.getDefault().post("FirstEvent");
--------------------------------------------------------------------------------
/app/src/main/res/raw/two_events_page.html:
--------------------------------------------------------------------------------
1 |
2 | Two events
3 |
4 | You should only see
You should see me and only me
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/unregistration.js:
--------------------------------------------------------------------------------
1 | function append(msg) {
2 | $('body').append('' + msg + '
');
3 | }
4 |
5 | var bus = Drekkar.getDefault();
6 |
7 | bus.register("Hello!", function(name) {
8 | append(name);
9 | bus.post("Whazup?");
10 | });
11 |
12 | bus.register("Bye", function(name) {
13 | append(name);
14 | setTimeout(
15 | function() {
16 | bus.post("Still around?");
17 | append("Still around just sent");
18 | },
19 | 4000
20 | );
21 | });
--------------------------------------------------------------------------------
/app/src/main/res/raw/unregistration_page.html:
--------------------------------------------------------------------------------
1 | Unregistration
2 |
3 |
4 | You should see
5 |
Hello!
6 | Bye
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Drekkar Test
3 | Settings
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/test/java/com/coshx/drekkartest/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkartest;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // Add this line
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/drekkar.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/drekkar/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/drekkar/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | group = 'com.github.coshx'
5 |
6 | android {
7 | compileSdkVersion 22
8 | buildToolsVersion "22.0.1"
9 |
10 | defaultConfig {
11 | minSdkVersion 15
12 | targetSdkVersion 22
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(dir: 'libs', include: ['*.jar'])
26 | testCompile 'junit:junit:4.12'
27 | compile 'com.android.support:appcompat-v7:22.2.1'
28 | }
29 |
30 | task javadoc(type: Javadoc) {
31 | source = android.sourceSets.main.java.srcDirs
32 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
33 | destinationDir = file("../javadoc/")
34 | failOnError false
35 | title = "Drekkar Reference"
36 | }
--------------------------------------------------------------------------------
/drekkar/drekkar-drekkar.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/drekkar/drekkar.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/drekkar/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/acadet/android-sdks/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/drekkar/src/androidTest/java/com/coshx/drekkar/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/drekkar/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/Arguments.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * Arguments
5 | */
6 | class Arguments {
7 | String busName;
8 | String eventName;
9 | String eventData;
10 |
11 | Arguments(String busName, String eventName, String eventData) {
12 | this.busName = busName;
13 | this.eventName = eventName;
14 | this.eventData = eventData;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/Callback.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * Callback
5 | *
6 | * Handles Drekkar's event.
7 | */
8 | public interface Callback {
9 |
10 | /**
11 | * Run when event is raised
12 | *
13 | * @param name Event's name
14 | * @param data Event's data (if any)
15 | */
16 | void run(String name, Object data);
17 | }
18 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/DataSerializer.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONException;
5 | import org.json.JSONObject;
6 |
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.Iterator;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * @class DataSerializer
15 | * @brief
16 | */
17 | class DataSerializer {
18 | private static Map toMap(JSONObject object) throws JSONException {
19 | Map dictionary = new HashMap();
20 | Iterator iterator = object.keys();
21 |
22 | while (iterator.hasNext()) {
23 | String key = iterator.next();
24 | Object value = object.get(key);
25 |
26 | if (value instanceof JSONArray) {
27 | value = toList((JSONArray) value);
28 | } else if (value instanceof JSONObject) {
29 | value = toMap((JSONObject) value);
30 | }
31 | dictionary.put(key, value);
32 | }
33 |
34 | return dictionary;
35 | }
36 |
37 | private static List toList(JSONArray array) throws JSONException {
38 | List list = new ArrayList();
39 |
40 | for (int i = 0, s = array.length(); i < s; i++) {
41 | Object o = array.get(i);
42 |
43 | if (o instanceof JSONObject) {
44 | o = toMap((JSONObject) o);
45 | } else if (o instanceof JSONArray) {
46 | o = toList((JSONArray) o);
47 | }
48 |
49 | list.add(o);
50 | }
51 |
52 | return list;
53 | }
54 |
55 | static String serialize(Object data) {
56 | String outcome;
57 |
58 | if (data instanceof Boolean) {
59 | outcome = ((Boolean) data) ? "true" : "false";
60 | } else if (data instanceof Integer || data instanceof Float || data instanceof Double) {
61 | outcome = data.toString();
62 | } else if (data instanceof String) {
63 | // As this string is going to be unwrapped from quotes, when passed to JS, all quotes need to be escaped
64 | outcome = data.toString();
65 | outcome = outcome.replaceAll("\"", "\\\\\\\"");
66 | outcome = outcome.replaceAll("'", "\\\\\\'");
67 | outcome = "\"" + outcome + "\"";
68 | } else if (data instanceof List) {
69 | // Array and Dictionary are serialized to JSON.
70 | // They should wrap only "basic" data (same types than supported ones)
71 | outcome = new JSONArray((List) data).toString();
72 | } else if (data instanceof Map) {
73 | outcome = new JSONObject((Map) data).toString();
74 | } else {
75 | outcome = null;
76 | }
77 |
78 | return outcome;
79 | }
80 |
81 | static Object deserialize(String input) {
82 | if (input.length() > 0) {
83 | if (input.length() >= 2) {
84 | char first = input.charAt(0), last = input.charAt(input.length() - 1);
85 |
86 | if (first == '[' && last == ']') {
87 | try {
88 | return toList(new JSONArray(input));
89 | } catch (Exception e) {
90 | return null;
91 | }
92 | } else if (first == '{' && last == '}') {
93 | try {
94 | return toMap(new JSONObject(input));
95 | } catch (Exception e) {
96 | return null;
97 | }
98 | }
99 | }
100 |
101 | if (input.equals("true")) {
102 | return true;
103 | } else if (input.equals("false")) {
104 | return false;
105 | }
106 |
107 | boolean isNumber = true;
108 | for (int i = 0, s = input.length(); i < s; i++) {
109 | char c = input.charAt(i);
110 |
111 | if (Character.isDigit(c) || c == '.' || c == ',') {
112 | // Do nothing
113 | } else {
114 | isNumber = false;
115 | break;
116 | }
117 | }
118 |
119 | if (isNumber) {
120 | try {
121 | return Integer.parseInt(input);
122 | } catch (Exception e1) {
123 | try {
124 | return Double.parseDouble(input);
125 | } catch (Exception e2) {
126 | return null;
127 | }
128 | }
129 | }
130 | }
131 |
132 | return input;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/Drekkar.java:
--------------------------------------------------------------------------------
1 | // _ _ _ _ _ _ _
2 | // /\ \ /\ \ /\ \ /\_\ /\_\ / /\ /\ \
3 | // / \ \____ / \ \ / \ \ / / / _ / / / _ / / \ / \ \
4 | // / /\ \_____\ / /\ \ \ / /\ \ \ / / / /\_\ / / / /\_\ / / /\ \ / /\ \ \
5 | // / / /\/___ // / /\ \_\ / / /\ \_\ / / /__/ / / / / /__/ / / / / /\ \ \ / / /\ \_\
6 | // / / / / / // / /_/ / / / /_/_ \/_/ / /\_____/ / / /\_____/ / / / / \ \ \ / / /_/ / /
7 | // / / / / / // / /__\/ / / /____/\ / /\_______/ / /\_______/ / / /___/ /\ \ / / /__\/ /
8 | // / / / / / // / /_____/ / /\____\/ / / /\ \ \ / / /\ \ \ / / /_____/ /\ \ / / /_____/
9 | // \ \ \__/ / // / /\ \ \ / / /______ / / / \ \ \ / / / \ \ \ / /_________/\ \ \ / / /\ \ \
10 | // \ \___\/ // / / \ \ \/ / /_______\/ / / \ \ \ / / / \ \ \ / / /_ __\ \_\/ / / \ \ \
11 | // \/_____/ \/_/ \_\/\/__________/\/_/ \_\_\\/_/ \_\_\\_\___\ /____/_/\/_/ \_\/
12 | //
13 |
14 | package com.coshx.drekkar;
15 |
16 | import android.webkit.WebView;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * Drekkar
23 | *
24 | * Main class of the library. Dispatches events among buses.
25 | */
26 | public class Drekkar {
27 | private static final Object busLock = new Object();
28 | static final String DEFAULT_BUS_NAME = "default";
29 |
30 | private String name;
31 | private List buses;
32 |
33 | Drekkar(String name) {
34 | this.name = name;
35 | this.buses = new ArrayList<>();
36 | }
37 |
38 | private void addBus(Object subscriber, WebView webView, WhenReady whenReady, Boolean
39 | inBackground) {
40 | EventBus bus;
41 |
42 | // Test if an existing bus matching provided pair already exists
43 | synchronized (busLock) {
44 | for (EventBus b : buses) {
45 | Object reference = b.getReference();
46 | WebView busWebView = b.getWebView();
47 |
48 | if (reference != null && reference.hashCode() == subscriber.hashCode()
49 | && busWebView != null && busWebView.hashCode() == webView.hashCode()) {
50 | if (inBackground) {
51 | b.whenReady(whenReady);
52 | } else {
53 | b.whenReadyOnMain(whenReady);
54 | }
55 | return;
56 | }
57 | }
58 | }
59 |
60 | bus = new EventBus(this, subscriber, webView);
61 |
62 | synchronized (busLock) {
63 | buses.add(bus);
64 | }
65 |
66 | if (inBackground) {
67 | bus.whenReady(whenReady);
68 | } else {
69 | bus.whenReadyOnMain(whenReady);
70 | }
71 |
72 | // Clean unused buses
73 | ThreadingHelper.background(
74 | new Runnable() {
75 | @Override
76 | public void run() {
77 | synchronized (busLock) {
78 | int i = 0;
79 | List toRemove = new ArrayList();
80 |
81 | for (EventBus b : buses) {
82 | if (b.getReference() == null && b.getWebView() == null) {
83 | // Watched pair was garbage collected. This bus is not needed anymore
84 | toRemove.add(i);
85 | b.willBeDeleted();
86 | }
87 | i++;
88 | }
89 |
90 | i = 0;
91 | for (Integer j : toRemove) {
92 | buses.remove(j - i);
93 | i++;
94 | }
95 | }
96 | }
97 | }
98 | );
99 | }
100 |
101 | void post(final String eventName, final T eventData) {
102 | ThreadingHelper.background(
103 | new Runnable() {
104 | @Override
105 | public void run() {
106 | String data;
107 | String toRun;
108 |
109 | if (eventData != null) {
110 | data = DataSerializer.serialize(eventData);
111 | } else {
112 | data = "null";
113 | }
114 |
115 | toRun = "Drekkar.";
116 |
117 | if (name.equals(DEFAULT_BUS_NAME)) {
118 | toRun += "getDefault()";
119 | } else {
120 | toRun += "get(\"" + name + "\")";
121 | }
122 |
123 | toRun += ".raise(\"" + eventName + "\", " + data + ")";
124 |
125 | synchronized (busLock) {
126 | for (EventBus b : buses) {
127 | b.forwardToJS(toRun);
128 | }
129 | }
130 | }
131 | }
132 | );
133 | }
134 |
135 | void deleteBus(EventBus bus) {
136 | synchronized (busLock) {
137 | int i = 0;
138 |
139 | for (EventBus b : buses) {
140 | if (b.equals(bus)) {
141 | buses.remove(i);
142 | return;
143 | }
144 | i++;
145 | }
146 | }
147 | }
148 |
149 | void dispatch(String busName, final String eventName, String rawData) {
150 | if (!busName.equals(name)) {
151 | // Different buses can use the same web view so same proxy
152 | // If not a potential receiver, ignore event
153 | return;
154 | }
155 |
156 | if (eventName.equals("DrekkarInit")) { // Reserved event name. Triggers whenReady
157 | synchronized (busLock) {
158 | for (EventBus b : buses) {
159 | b.onInit(); // Run on main/current thread
160 | }
161 | }
162 | } else {
163 | final Object eventData = (rawData == null) ? null : DataSerializer.deserialize(rawData);
164 | ThreadingHelper.background(
165 | new Runnable() {
166 | @Override
167 | public void run() {
168 | synchronized (busLock) {
169 | for (EventBus b : buses) {
170 | final EventBus finalBus = b;
171 | ThreadingHelper.background(
172 | new Runnable() {
173 | @Override
174 | public void run() {
175 | finalBus.raise(eventName, eventData);
176 | }
177 | }
178 | );
179 | }
180 | }
181 | }
182 | }
183 | );
184 | }
185 | }
186 |
187 | /**
188 | * Current name
189 | */
190 | public String getName() {
191 | return name;
192 | }
193 |
194 | /**
195 | * Returns default bus
196 | *
197 | * @param subscriber Subscriber (usually the activity/current context)
198 | * @param webView WebView to watch
199 | * @param whenReady Action to run when JS counterpart is ready
200 | * @return Current instance
201 | */
202 | public static Drekkar getDefault(Object subscriber, WebView webView, WhenReady whenReady) {
203 | Drekkar d = DrekkarFactory.getDefault();
204 | d.addBus(subscriber, webView, whenReady, true);
205 | return d;
206 | }
207 |
208 | /**
209 | * Returns default bus and runs callback on main thread
210 | *
211 | * @param subscriber Subscriber (usually the activity/current context)
212 | * @param webView WebView to watch
213 | * @param whenReady Action to run when JS counterpart is ready
214 | * @return Current instance
215 | */
216 | public static Drekkar getDefault(Object subscriber, WebView webView, WhenReadyOnMain
217 | whenReady) {
218 | Drekkar d = DrekkarFactory.getDefault();
219 | d.addBus(subscriber, webView, whenReady, false);
220 | return d;
221 | }
222 |
223 | /**
224 | * Returns custom bus
225 | *
226 | * @param subscriber Subscriber (usually the activity/current context)
227 | * @param name Bus name
228 | * @param webView WebView to watch
229 | * @param whenReady Action to run when JS counterpart is ready
230 | * @return Current instance
231 | */
232 | public static Drekkar get(Object subscriber, String name, WebView webView, WhenReady
233 | whenReady) {
234 | Drekkar d = DrekkarFactory.get(name);
235 | d.addBus(subscriber, webView, whenReady, true);
236 | return d;
237 | }
238 |
239 | /**
240 | * Returns custom bus and runs callback on main thread
241 | *
242 | * @param subscriber Subscriber (usually the activity/current context)
243 | * @param name Bus name
244 | * @param webView WebView to watch
245 | * @param whenReady Action to run when JS counterpart is ready
246 | * @return Current instance
247 | */
248 | public static Drekkar get(Object subscriber, String name, WebView webView, WhenReadyOnMain
249 | whenReady) {
250 | Drekkar d = DrekkarFactory.get(name);
251 | d.addBus(subscriber, webView, whenReady, false);
252 | return d;
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/DrekkarFactory.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * DrekkarFactory
8 | *
9 | * Manages the different Drekkar instances and ensures they are all singletons
10 | */
11 | class DrekkarFactory {
12 | private static final Object defaultBusLock = new Object();
13 | private static Drekkar defaultBus;
14 |
15 | private static final Object creationLock = new Object();
16 | // A lock per bus. Uses lock above when initializing
17 | private static Map busLocks = new HashMap<>();
18 | private static Map buses = new HashMap<>();
19 |
20 | private static Object getLock(String name) {
21 | if (busLocks.containsKey(name)) {
22 | return busLocks.get(name);
23 | } else {
24 | synchronized (creationLock) {
25 | if (busLocks.containsKey(name)) {
26 | return busLocks.get(name);
27 | } else {
28 | Object o = new Object();
29 | busLocks.put(name, o);
30 | return o;
31 | }
32 | }
33 | }
34 | }
35 |
36 | static Drekkar getDefault() {
37 | if (defaultBus != null) {
38 | return defaultBus;
39 | } else {
40 | synchronized (defaultBusLock) {
41 | if (defaultBus == null) {
42 | defaultBus = new Drekkar(Drekkar.DEFAULT_BUS_NAME);
43 | }
44 | return defaultBus;
45 | }
46 | }
47 | }
48 |
49 | static Drekkar get(String name) {
50 | if (name.equals(Drekkar.DEFAULT_BUS_NAME)) {
51 | return getDefault();
52 | } else {
53 | if (buses.containsKey(name)) {
54 | return buses.get(name);
55 | } else {
56 | synchronized (getLock(name)) {
57 | if (buses.containsKey(name)) {
58 | return buses.get(name);
59 | } else {
60 | Drekkar bus = new Drekkar(name);
61 | buses.put(name, bus);
62 | return bus;
63 | }
64 | }
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/EventBus.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import android.webkit.WebView;
4 |
5 | import java.lang.ref.WeakReference;
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | /**
12 | * EventBus
13 | *
14 | * In charge of watching a subscriber / webview pair.
15 | *
16 | * Deals with any request from the user side, as well as the watched pair, and forward them to the
17 | * dispatcher.
18 | */
19 | public class EventBus {
20 | private class Initializer {
21 | WhenReady callback;
22 | Boolean inBackground;
23 |
24 | Initializer(WhenReady callback, Boolean inBackground) {
25 | this.callback = callback;
26 | this.inBackground = inBackground;
27 | }
28 | }
29 |
30 | private final Object initializationLock = new Object();
31 | private final Object subscriberLock = new Object();
32 |
33 | private WeakReference reference;
34 | private WeakReference webView;
35 | private WeakReference dispatcher;
36 | /**
37 | * The field below prevents the onMessage method to be public and accessible by users
38 | */
39 | private IWebViewJSEndpoint embeddedEndpoint;
40 |
41 | /**
42 | * Bus subscribers
43 | */
44 | private List subscribers;
45 |
46 | /**
47 | * Denotes if the bus has received init event from JS
48 | */
49 | private Boolean isInitialized;
50 |
51 | /**
52 | * Pending initialization subscribers
53 | */
54 | private List initializers;
55 | // Buffer to save initializers temporary, in order to prevent them from being garbage collected
56 | private Map onGoingInitializers;
57 | private int onGoingInitializersId;
58 |
59 | EventBus(Drekkar dispatcher, Object reference, WebView webView) {
60 | this.dispatcher = new WeakReference<>(dispatcher);
61 | this.reference = new WeakReference<>(reference);
62 | this.webView = new WeakReference<>(webView);
63 | this.isInitialized = false;
64 | this.subscribers = new ArrayList<>();
65 | this.initializers = new ArrayList<>();
66 | this.onGoingInitializers = new HashMap<>();
67 | this.onGoingInitializersId = 0;
68 |
69 | this.embeddedEndpoint = new IWebViewJSEndpoint() {
70 | @Override
71 | public void onMessage(String busName, String eventName, String rawData) {
72 | Drekkar d = EventBus.this.dispatcher.get();
73 |
74 | if (d != null) {
75 | d.dispatch(busName, eventName, rawData);
76 | }
77 | }
78 | };
79 |
80 | WebViewJSEndpointMediator.subscribe(webView, this.embeddedEndpoint);
81 | }
82 |
83 | private void unsubscribeFromProxy() {
84 | WebView w = webView.get();
85 |
86 | if (w != null) {
87 | WebViewJSEndpointMediator.unsubscribe(w, this.embeddedEndpoint);
88 | }
89 | }
90 |
91 | Object getReference() {
92 | return reference.get();
93 | }
94 |
95 | WebView getWebView() {
96 | return webView.get();
97 | }
98 |
99 | void willBeDeleted() {
100 | unsubscribeFromProxy();
101 | }
102 |
103 | /**
104 | * Runs JS script into current context
105 | */
106 | void forwardToJS(final String toRun) {
107 | ThreadingHelper.main(
108 | new Runnable() {
109 | @Override
110 | public void run() {
111 | WebView w = webView.get();
112 | if (w != null) {
113 | w.loadUrl("javascript:" + toRun);
114 | }
115 | }
116 | }
117 | );
118 | }
119 |
120 | void onInit() {
121 | // Initialization must be run on the main thread. Otherwise, some events would be triggered before onReady
122 | // has been run and hence be lost.
123 | if (isInitialized) {
124 | return;
125 | }
126 |
127 | synchronized (initializationLock) {
128 | if (isInitialized) {
129 | return;
130 | }
131 |
132 | for (Initializer initializer : initializers) {
133 | final int index = onGoingInitializersId;
134 | final WhenReady callback = initializer.callback;
135 | Runnable action = new Runnable() {
136 | @Override
137 | public void run() {
138 | callback.run(EventBus.this);
139 | onGoingInitializers.remove(index);
140 | }
141 | };
142 |
143 | onGoingInitializers.put(index, initializer);
144 | onGoingInitializersId++;
145 |
146 | if (initializer.inBackground) {
147 | ThreadingHelper.background(action);
148 | } else {
149 | ThreadingHelper.main(action);
150 | }
151 | }
152 |
153 | initializers = new ArrayList<>();
154 | isInitialized = true;
155 | }
156 | }
157 |
158 | /**
159 | * Allows dispatcher to fire any event on this bus
160 | */
161 | void raise(final String name, final Object data) {
162 | synchronized (subscriberLock) {
163 | for (EventSubscriber s : subscribers) {
164 | if (s.name.equals(name)) {
165 | final EventSubscriber finalS = s;
166 | Runnable action = new Runnable() {
167 | @Override
168 | public void run() {
169 | finalS.callback.run(name, data);
170 | }
171 | };
172 |
173 | if (finalS.inBackground) {
174 | ThreadingHelper.background(action);
175 | } else {
176 | ThreadingHelper.main(action);
177 | }
178 | }
179 | }
180 | }
181 | }
182 |
183 | void whenReady(final WhenReady callback) {
184 | ThreadingHelper.background(
185 | new Runnable() {
186 | @Override
187 | public void run() {
188 | if (isInitialized) {
189 | ThreadingHelper.background(
190 | new Runnable() {
191 | @Override
192 | public void run() {
193 | callback.run(EventBus.this);
194 | }
195 | }
196 | );
197 | } else {
198 | synchronized (initializationLock) {
199 | if (isInitialized) {
200 | ThreadingHelper.background(
201 | new Runnable() {
202 | @Override
203 | public void run() {
204 | callback.run(EventBus.this);
205 | }
206 | }
207 | );
208 | } else {
209 | initializers.add(new Initializer(callback, true));
210 | }
211 | }
212 | }
213 | }
214 | }
215 | );
216 | }
217 |
218 | void whenReadyOnMain(final WhenReady callback) {
219 | ThreadingHelper.background(
220 | new Runnable() {
221 | @Override
222 | public void run() {
223 | if (isInitialized) {
224 | ThreadingHelper.main(
225 | new Runnable() {
226 | @Override
227 | public void run() {
228 | callback.run(EventBus.this);
229 | }
230 | }
231 | );
232 | } else {
233 | synchronized (initializationLock) {
234 | if (isInitialized) {
235 | ThreadingHelper.main(
236 | new Runnable() {
237 | @Override
238 | public void run() {
239 | callback.run(EventBus.this);
240 | }
241 | }
242 | );
243 | } else {
244 | initializers.add(new Initializer(callback, false));
245 | }
246 | }
247 | }
248 | }
249 | }
250 | );
251 | }
252 |
253 | /**
254 | * Current name
255 | */
256 | public String getName() {
257 | return dispatcher.get().getName();
258 | }
259 |
260 | /**
261 | * Posts event
262 | *
263 | * @param eventName Event's name
264 | */
265 | public void post(String eventName) {
266 | Drekkar d = dispatcher.get();
267 | if (d != null) {
268 | d.post(eventName, null);
269 | }
270 | }
271 |
272 | /**
273 | * Posts event with extra data
274 | *
275 | * @param eventName Event's name
276 | * @param data Data to post (see documentation for supported types)
277 | */
278 | public void post(String eventName, T data) {
279 | Drekkar d = dispatcher.get();
280 |
281 | if (d != null) {
282 | d.post(eventName, data);
283 | }
284 | }
285 |
286 | /**
287 | * Subscribes to event. Callback is run with the event's name and extra data (if any).
288 | *
289 | * @param eventName Event to watch
290 | * @param callback Action to run when fired
291 | */
292 | public void register(String eventName, Callback callback) {
293 | synchronized (subscriberLock) {
294 | subscribers.add(new EventSubscriber(eventName, callback, true));
295 | }
296 | }
297 |
298 | /**
299 | * Subscribes to event. Callback is run on main thread with the event's name and extra data (if
300 | * any).
301 | *
302 | * @param eventName Event to watch
303 | * @param callback Action to run when fired
304 | */
305 | public void registerOnMain(String eventName, Callback callback) {
306 | synchronized (subscriberLock) {
307 | subscribers.add(new EventSubscriber(eventName, callback, false));
308 | }
309 | }
310 |
311 | /**
312 | * Unregisters subscriber from bus
313 | */
314 | public void unregister() {
315 | Drekkar d = dispatcher.get();
316 |
317 | d.deleteBus(this);
318 |
319 | unsubscribeFromProxy();
320 |
321 | dispatcher = new WeakReference(null);
322 | reference = new WeakReference(null);
323 | webView = new WeakReference(null);
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/EventSubscriber.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * @class EventSubscriber
5 | * @brief Internal class storing bus subscribers
6 | */
7 | class EventSubscriber {
8 | String name;
9 | Callback callback;
10 | Boolean inBackground;
11 |
12 | EventSubscriber(String name, Callback callback, Boolean inBackground) {
13 | this.name = name;
14 | this.callback = callback;
15 | this.inBackground = inBackground;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/IWebViewJSEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * @class IWebViewJSEndpoint
5 | * @brief
6 | */
7 | interface IWebViewJSEndpoint {
8 | void onMessage(String busName, String eventName, String rawData);
9 | }
10 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/ThreadingHelper.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 |
4 | import android.os.AsyncTask;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 |
8 | /**
9 | * @class ThreadingHelper
10 | * @brief
11 | */
12 | class ThreadingHelper {
13 | static void background(final Runnable action) {
14 | main(new Runnable() {
15 | @Override
16 | public void run() {
17 | AsyncTask.execute(action);
18 | }
19 | });
20 | }
21 |
22 | static void main(final Runnable action) {
23 | Handler h = new Handler(Looper.getMainLooper());
24 | h.post(action);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/WebViewJSEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import android.webkit.JavascriptInterface;
4 | import android.webkit.WebView;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * @class WebViewJSEndpoint
11 | * @brief Dispatches events to subscribers
12 | */
13 | class WebViewJSEndpoint {
14 | private final Object subscriberLock = new Object();
15 |
16 | private List subscribers = new ArrayList<>();
17 |
18 | WebViewJSEndpoint(final WebView webView) {
19 | ThreadingHelper.main(
20 | new Runnable() {
21 | @Override
22 | public void run() {
23 | webView.addJavascriptInterface(
24 | WebViewJSEndpoint.this,
25 | "DrekkarWebViewJSEndpoint"
26 | );
27 | }
28 | }
29 | );
30 | }
31 |
32 | void subscribe(IWebViewJSEndpoint subscriber) {
33 | synchronized (subscriberLock) {
34 | for (IWebViewJSEndpoint e : subscribers) {
35 | if (e.hashCode() == subscriber.hashCode()) {
36 | return;
37 | }
38 | }
39 |
40 | subscribers.add(subscriber);
41 | }
42 | }
43 |
44 | void unsubscribe(IWebViewJSEndpoint subscriber) {
45 | synchronized (subscriberLock) {
46 | int i = 0;
47 |
48 | for (IWebViewJSEndpoint e : subscribers) {
49 | if (e.hashCode() == subscriber.hashCode()) {
50 | subscribers.remove(i);
51 | return;
52 | }
53 | i++;
54 | }
55 | }
56 | }
57 |
58 | boolean hasSubscribers() {
59 | return subscribers.size() > 0;
60 | }
61 |
62 | void willBeDeleted(final WebView webview) {
63 | ThreadingHelper.main(
64 | new Runnable() {
65 | @Override
66 | public void run() {
67 | webview.removeJavascriptInterface("DrekkarWebViewJSEndpoint");
68 | }
69 | }
70 | );
71 | }
72 |
73 | @JavascriptInterface
74 | public void send(final String busName, final String eventName, final String eventData) {
75 | synchronized (subscriberLock) {
76 | for (IWebViewJSEndpoint e : subscribers) {
77 | final IWebViewJSEndpoint finalE = e;
78 |
79 | ThreadingHelper.background(
80 | new Runnable() {
81 | @Override
82 | public void run() {
83 | finalE.onMessage(busName, eventName, eventData);
84 | }
85 | }
86 | );
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/WebViewJSEndpointMediator.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import android.webkit.WebView;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | /**
9 | * @class WebViewJSEndpointMediator
10 | * @brief
11 | */
12 | class WebViewJSEndpointMediator {
13 | private final static Object creationLock = new Object();
14 |
15 | private static Map proxies = new HashMap<>();
16 |
17 | static void subscribe(WebView webView, IWebViewJSEndpoint observer) {
18 | int key = webView.hashCode();
19 |
20 | if (proxies.containsKey(key)) {
21 | proxies.get(key).subscribe(observer);
22 | } else {
23 | synchronized (creationLock) {
24 | if (proxies.containsKey(key)) {
25 | proxies.get(key).subscribe(observer);
26 | } else {
27 | WebViewJSEndpoint proxy = new WebViewJSEndpoint(webView);
28 | proxy.subscribe(observer);
29 | proxies.put(key, proxy);
30 | }
31 | }
32 | }
33 | }
34 |
35 | static void unsubscribe(WebView webView, IWebViewJSEndpoint observer) {
36 | int key = webView.hashCode();
37 |
38 | if (proxies.containsKey(key)) {
39 | WebViewJSEndpoint proxy = proxies.get(key);
40 |
41 | proxy.unsubscribe(observer);
42 |
43 | if (!proxy.hasSubscribers()) {
44 | synchronized (creationLock) {
45 | if (!proxy.hasSubscribers()) {
46 | proxy.willBeDeleted(webView);
47 | proxies.remove(key);
48 | }
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/WhenReady.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * WhenReady
5 | *
6 | * Callback to run when bus is ready to use
7 | */
8 | public interface WhenReady {
9 | void run(EventBus bus);
10 | }
11 |
--------------------------------------------------------------------------------
/drekkar/src/main/java/com/coshx/drekkar/WhenReadyOnMain.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | /**
4 | * WhenReadyOnMain
5 | *
6 | * Callback to run on main thread when bus is ready to use
7 | */
8 | public interface WhenReadyOnMain extends WhenReady {
9 | }
10 |
--------------------------------------------------------------------------------
/drekkar/src/main/res/raw/drekkar.js:
--------------------------------------------------------------------------------
1 | var Drekkar;
2 |
3 | Drekkar = (function() {
4 | Drekkar["default"] = null;
5 |
6 | Drekkar.buses = [];
7 |
8 | function Drekkar(name) {
9 | this.name = name;
10 | this.subscribers = [];
11 | }
12 |
13 | Drekkar.prototype._post = function(eventName, data) {
14 | return setTimeout(((function(_this) {
15 | return function() {
16 | var dataToSend;
17 | dataToSend = null;
18 | if (data != null) {
19 | if (data instanceof Array || data instanceof Object) {
20 | dataToSend = JSON.stringify(data);
21 | } else {
22 | dataToSend = data;
23 | }
24 | }
25 | return DrekkarWebViewJSEndpoint.send(_this.name, eventName, dataToSend);
26 | };
27 | })(this)), 0);
28 | };
29 |
30 | Drekkar.prototype.getName = function() {
31 | return this.name;
32 | };
33 |
34 | Drekkar.prototype.post = function(name, data) {
35 | return this._post(name, data);
36 | };
37 |
38 | Drekkar.prototype.register = function(name, callback) {
39 | return this.subscribers.push({
40 | name: name,
41 | callback: callback
42 | });
43 | };
44 |
45 | Drekkar.prototype.raise = function(name, data) {
46 | var e, i, len, parsedData, ref, results;
47 | parsedData = null;
48 | if (data instanceof Array || data instanceof Object || (typeof data === "string" || data instanceof String)) {
49 | parsedData = data;
50 | } else {
51 | parsedData = JSON.parse(data);
52 | }
53 | ref = this.subscribers;
54 | results = [];
55 | for (i = 0, len = ref.length; i < len; i++) {
56 | e = ref[i];
57 | if (e.name === name) {
58 | results.push(e.callback(name, parsedData));
59 | } else {
60 | results.push(void 0);
61 | }
62 | }
63 | return results;
64 | };
65 |
66 | Drekkar.getDefault = function() {
67 | if (Drekkar["default"] == null) {
68 | Drekkar["default"] = new Drekkar("default");
69 | Drekkar["default"].post("DrekkarInit");
70 | }
71 | return Drekkar["default"];
72 | };
73 |
74 | Drekkar.get = function(name) {
75 | var b, i, len, ref;
76 | ref = Drekkar.buses;
77 | for (i = 0, len = ref.length; i < len; i++) {
78 | b = ref[i];
79 | if (b.getName() === name) {
80 | return b;
81 | }
82 | }
83 | b = new Drekkar(name);
84 | Drekkar.buses.push(b);
85 | b.post("DrekkarInit");
86 | return b;
87 | };
88 |
89 | return Drekkar;
90 |
91 | })();
92 |
--------------------------------------------------------------------------------
/drekkar/src/main/res/raw/drekkar_min.js:
--------------------------------------------------------------------------------
1 | /** Drekkar navajo-white-butterfly-v0.1.2 - https://github.com/coshx/drekkar */
2 | var Drekkar;Drekkar=function(){function Drekkar(name){this.name=name,this.subscribers=[]}return Drekkar["default"]=null,Drekkar.buses=[],Drekkar.prototype._post=function(eventName,data){return setTimeout(function(_this){return function(){var dataToSend;return dataToSend=null,null!=data&&(dataToSend=data instanceof Array||data instanceof Object?JSON.stringify(data):data),DrekkarWebViewJSEndpoint.send(_this.name,eventName,dataToSend)}}(this),0)},Drekkar.prototype.getName=function(){return this.name},Drekkar.prototype.post=function(name,data){return this._post(name,data)},Drekkar.prototype.register=function(name,callback){return this.subscribers.push({name:name,callback:callback})},Drekkar.prototype.raise=function(name,data){var e,i,len,parsedData,ref,results;for(parsedData=null,parsedData=data instanceof Array||data instanceof Object||"string"==typeof data||data instanceof String?data:JSON.parse(data),ref=this.subscribers,results=[],i=0,len=ref.length;len>i;i++)e=ref[i],e.name===name?results.push(e.callback(name,parsedData)):results.push(void 0);return results},Drekkar.getDefault=function(){return null==Drekkar["default"]&&(Drekkar["default"]=new Drekkar("default"),Drekkar["default"].post("DrekkarInit")),Drekkar["default"]},Drekkar.get=function(name){var b,i,len,ref;for(ref=Drekkar.buses,i=0,len=ref.length;len>i;i++)if(b=ref[i],b.getName()===name)return b;return b=new Drekkar(name),Drekkar.buses.push(b),b.post("DrekkarInit"),b},Drekkar}();
--------------------------------------------------------------------------------
/drekkar/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Drekkar
3 |
4 |
--------------------------------------------------------------------------------
/drekkar/src/test/java/com/coshx/drekkar/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.coshx.drekkar;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coshx/drekkar/174910889c021fb35255cccc7810b06c0a6dffd3/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
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-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/js/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 | 'use strict';
3 |
4 | var version = 'navajo-white-butterfly-v0.1.2';
5 |
6 | // Project configuration
7 | grunt.initConfig({
8 | coffee: {
9 | dist: {
10 | options: {
11 | bare: true,
12 | sourceMap: false
13 | },
14 | files: {
15 | '../drekkar/src/main/res/raw/drekkar.js': 'drekkar.coffee'
16 | }
17 | }
18 | },
19 | coffeelint: {
20 | dist: {
21 | options: {
22 | configFile: 'coffeelint-config.json'
23 | },
24 | files: {
25 | src: [ 'drekkar.coffee' ]
26 | }
27 | }
28 | },
29 | uglify: {
30 | dist: {
31 | options: {
32 | mangle: false,
33 | compression: true,
34 | preserveComments: false,
35 | banner: '/** Drekkar ' + version + ' - https://github.com/coshx/drekkar */\n'
36 | },
37 | files: {
38 | '../drekkar/src/main/res/raw/drekkar_min.js': '../drekkar/src/main/res/raw/drekkar.js'
39 | }
40 | }
41 | },
42 | watch: {
43 | coffee: {
44 | options: {
45 | atBegin: true,
46 | interrupt: true
47 | },
48 | tasks: ['coffee'],
49 | files: '*.coffee'
50 | }
51 | }
52 | });
53 |
54 | // These plugins provide necessary tasks
55 | grunt.loadNpmTasks('grunt-contrib-coffee');
56 | grunt.loadNpmTasks('grunt-coffeelint');
57 | grunt.loadNpmTasks('grunt-contrib-uglify');
58 | grunt.loadNpmTasks('grunt-contrib-watch');
59 |
60 | // Default task
61 | grunt.registerTask('default', ['coffeelint', 'coffee']);
62 | grunt.registerTask('release', ['default', 'uglify']);
63 | };
64 |
--------------------------------------------------------------------------------
/js/coffeelint-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "coffeescript_error": {
3 | "level": "error"
4 | },
5 | "arrow_spacing": {
6 | "name": "arrow_spacing",
7 | "level": "warn"
8 | },
9 | "no_tabs": {
10 | "name": "no_tabs",
11 | "level": "error"
12 | },
13 | "no_trailing_whitespace": {
14 | "name": "no_trailing_whitespace",
15 | "level": "warn",
16 | "allowed_in_comments": false,
17 | "allowed_in_empty_lines": true
18 | },
19 | "max_line_length": {
20 | "name": "max_line_length",
21 | "value": 80,
22 | "level": "warn",
23 | "limitComments": true
24 | },
25 | "line_endings": {
26 | "name": "line_endings",
27 | "level": "ignore",
28 | "value": "unix"
29 | },
30 | "no_trailing_semicolons": {
31 | "name": "no_trailing_semicolons",
32 | "level": "error"
33 | },
34 | "indentation": {
35 | "name": "indentation",
36 | "value": 2,
37 | "level": "error"
38 | },
39 | "camel_case_classes": {
40 | "name": "camel_case_classes",
41 | "level": "error"
42 | },
43 | "colon_assignment_spacing": {
44 | "name": "colon_assignment_spacing",
45 | "level": "warn",
46 | "spacing": {
47 | "left": 0,
48 | "right": 1
49 | }
50 | },
51 | "no_implicit_braces": {
52 | "name": "no_implicit_braces",
53 | "level": "ignore",
54 | "strict": true
55 | },
56 | "no_plusplus": {
57 | "name": "no_plusplus",
58 | "level": "ignore"
59 | },
60 | "no_throwing_strings": {
61 | "name": "no_throwing_strings",
62 | "level": "error"
63 | },
64 | "no_backticks": {
65 | "name": "no_backticks",
66 | "level": "error"
67 | },
68 | "no_implicit_parens": {
69 | "name": "no_implicit_parens",
70 | "level": "ignore"
71 | },
72 | "no_empty_param_list": {
73 | "name": "no_empty_param_list",
74 | "level": "warn"
75 | },
76 | "no_stand_alone_at": {
77 | "name": "no_stand_alone_at",
78 | "level": "ignore"
79 | },
80 | "space_operators": {
81 | "name": "space_operators",
82 | "level": "error"
83 | },
84 | "duplicate_key": {
85 | "name": "duplicate_key",
86 | "level": "error"
87 | },
88 | "empty_constructor_needs_parens": {
89 | "name": "empty_constructor_needs_parens",
90 | "level": "ignore"
91 | },
92 | "cyclomatic_complexity": {
93 | "name": "cyclomatic_complexity",
94 | "value": 10,
95 | "level": "warn"
96 | },
97 | "newlines_after_classes": {
98 | "name": "newlines_after_classes",
99 | "value": 3,
100 | "level": "ignore"
101 | },
102 | "no_unnecessary_fat_arrows": {
103 | "name": "no_unnecessary_fat_arrows",
104 | "level": "warn"
105 | },
106 | "missing_fat_arrows": {
107 | "name": "missing_fat_arrows",
108 | "level": "warn"
109 | },
110 | "non_empty_constructor_needs_parens": {
111 | "name": "non_empty_constructor_needs_parens",
112 | "level": "ignore"
113 | }
114 | }
--------------------------------------------------------------------------------
/js/drekkar.coffee:
--------------------------------------------------------------------------------
1 | # @class Drekkar
2 | # @brief Drekkar JS bus
3 | class Drekkar
4 | @default = null
5 | @buses = []
6 |
7 | constructor: (name) ->
8 | @name = name
9 | @subscribers = []
10 |
11 | # Internal method for posting
12 | _post: (eventName, data) ->
13 | # shouldLoadRequest is only triggered when a new content is required
14 | # Ajax requests are useless
15 | setTimeout (() =>
16 | dataToSend = null
17 | if data?
18 | if data instanceof Array or data instanceof Object
19 | dataToSend = JSON.stringify(data)
20 | else
21 | dataToSend = data
22 | DrekkarWebViewJSEndpoint.send @name, eventName, dataToSend
23 | ), 0
24 |
25 | getName: () ->
26 | @name
27 |
28 | post: (name, data) ->
29 | @_post name, data
30 |
31 | register: (name, callback) ->
32 | @subscribers.push { name: name, callback: callback }
33 |
34 | # Internal method only. Called by Android part for triggering events on the bus
35 | raise: (name, data) ->
36 | parsedData = null
37 | if data instanceof Array or data instanceof Object or (typeof data == "string" or data instanceof String)
38 | # Data are already parsed, nothing to do
39 | parsedData = data
40 | else
41 | parsedData = JSON.parse data
42 | for e in @subscribers
43 | e.callback(name, parsedData) if e.name == name
44 |
45 | @getDefault: ->
46 | unless Drekkar.default?
47 | Drekkar.default = new Drekkar("default")
48 | Drekkar.default.post "DrekkarInit"
49 | Drekkar.default
50 |
51 | @get: (name) ->
52 | for b in Drekkar.buses
53 | if b.getName() == name
54 | return b
55 |
56 | b = new Drekkar name
57 | Drekkar.buses.push b
58 | b.post "DrekkarInit"
59 | return b
--------------------------------------------------------------------------------
/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js",
3 | "version": "0.0.0",
4 | "dependencies": {},
5 | "devDependencies": {
6 | "coffeelint": "^1.9.7",
7 | "grunt": "~0.4.2",
8 | "grunt-coffeelint": "0.0.13",
9 | "grunt-contrib-coffee": "^0.13.0",
10 | "grunt-contrib-uglify": "^0.9.1",
11 | "grunt-contrib-watch": "~0.6.1"
12 | }
13 | }
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coshx/drekkar/174910889c021fb35255cccc7810b06c0a6dffd3/logo.png
--------------------------------------------------------------------------------
/original_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coshx/drekkar/174910889c021fb35255cccc7810b06c0a6dffd3/original_logo.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':drekkar'
2 |
--------------------------------------------------------------------------------
/src.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------