├── cordova
├── emulate.bat
├── appinfo.jar
├── BOOM.bat
├── log.bat
├── clean.bat
├── debug.bat
├── cordova.bat
└── cordova.js
├── psd
├── icon.psd
└── splash.psd
├── res
├── drawable
│ ├── icon.png
│ └── notification.png
├── drawable-hdpi
│ ├── icon.png
│ ├── ic_launcher.png
│ └── notification.png
├── drawable-ldpi
│ ├── icon.png
│ ├── ic_launcher.png
│ └── notification.png
├── drawable-mdpi
│ ├── icon.png
│ ├── ic_launcher.png
│ └── notification.png
├── drawable-xhdpi
│ ├── icon.png
│ ├── ic_launcher.png
│ └── notification.png
├── values
│ └── strings.xml
├── layout
│ └── main.xml
└── xml
│ └── config.xml
├── dist
├── lets-chat-001.apk
└── lets-chat-002.apk
├── libs
└── cordova-2.2.0.jar
├── assets
└── www
│ ├── media
│ ├── img
│ │ └── maze.png
│ ├── js
│ │ ├── vendor
│ │ │ ├── uri.js
│ │ │ ├── toe.js
│ │ │ ├── statusbarnotification.js
│ │ │ ├── store.js
│ │ │ ├── moment.js
│ │ │ ├── underscore.js
│ │ │ ├── backbone.js
│ │ │ └── ratchet.js
│ │ ├── models.js
│ │ ├── util
│ │ │ └── message.js
│ │ ├── client.js
│ │ └── views.js
│ ├── font
│ │ ├── FontAwesome.otf
│ │ ├── Pacifico-webfont.eot
│ │ ├── Pacifico-webfont.ttf
│ │ ├── Pacifico-webfont.woff
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ └── fontawesome-webfont.woff
│ └── css
│ │ ├── style.less
│ │ ├── style
│ │ ├── login.less
│ │ ├── base.less
│ │ └── chat.less
│ │ ├── vendor
│ │ └── font-awesome.less
│ │ └── style.css
│ ├── config.xml
│ └── index.html
├── README.md
├── .settings
└── org.eclipse.jdt.core.prefs
├── .classpath
├── project.properties
├── ant.properties
├── .gitignore
├── .project
├── src
└── com
│ ├── LetsChat
│ └── LetsChat.java
│ └── phonegap
│ └── plugins
│ └── statusBarNotification
│ ├── StatusNotificationIntent.java
│ └── StatusBarNotification.java
└── AndroidManifest.xml
/cordova/emulate.bat:
--------------------------------------------------------------------------------
1 | %~dp0\cordova.bat emulate
2 |
--------------------------------------------------------------------------------
/psd/icon.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/psd/icon.psd
--------------------------------------------------------------------------------
/psd/splash.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/psd/splash.psd
--------------------------------------------------------------------------------
/cordova/appinfo.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/cordova/appinfo.jar
--------------------------------------------------------------------------------
/res/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable/icon.png
--------------------------------------------------------------------------------
/dist/lets-chat-001.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/dist/lets-chat-001.apk
--------------------------------------------------------------------------------
/dist/lets-chat-002.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/dist/lets-chat-002.apk
--------------------------------------------------------------------------------
/libs/cordova-2.2.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/libs/cordova-2.2.0.jar
--------------------------------------------------------------------------------
/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/assets/www/media/img/maze.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/img/maze.png
--------------------------------------------------------------------------------
/res/drawable/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable/notification.png
--------------------------------------------------------------------------------
/assets/www/media/js/vendor/uri.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/js/vendor/uri.js
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-hdpi/notification.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-ldpi/notification.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-mdpi/notification.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/res/drawable-xhdpi/notification.png
--------------------------------------------------------------------------------
/assets/www/media/font/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/FontAwesome.otf
--------------------------------------------------------------------------------
/assets/www/media/font/Pacifico-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/Pacifico-webfont.eot
--------------------------------------------------------------------------------
/assets/www/media/font/Pacifico-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/Pacifico-webfont.ttf
--------------------------------------------------------------------------------
/assets/www/media/font/Pacifico-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/Pacifico-webfont.woff
--------------------------------------------------------------------------------
/assets/www/media/font/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/assets/www/media/font/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/assets/www/media/font/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hhaidar/lets-chat-android/HEAD/assets/www/media/font/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lets Chat
4 |
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Let's Chat Android Client
2 | =================
3 |
4 | Writing an Android client for our little chat app...
5 |
6 | 
7 |
--------------------------------------------------------------------------------
/assets/www/media/css/style.less:
--------------------------------------------------------------------------------
1 | @import 'vendor/ratchet.css';
2 | @import 'vendor/font-awesome.less';
3 |
4 | @import 'style/base.less';
5 | @import 'style/login.less';
6 | @import 'style/chat.less';
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/assets/www/media/js/models.js:
--------------------------------------------------------------------------------
1 | var UserModel = Backbone.Model.extend({});
2 |
3 | var UsersCollection = Backbone.Collection.extend({
4 | model: UserModel
5 | });
6 |
7 | var MessageModel = Backbone.Model.extend({});
8 |
9 | var MessagesCollection = Backbone.Collection.extend({
10 | model: MessageModel
11 | });
12 |
13 | var RoomModel = Backbone.Model.extend({
14 | initialize: function() {
15 | this.messages = new MessagesCollection();
16 | this.users = new UsersCollection();
17 | }
18 | });
19 |
20 | var RoomsCollection = Backbone.Collection.extend({
21 | model: RoomModel
22 | });
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ANDROID / ECLIPSE
2 |
3 | # built application files
4 | *.apk
5 | *.ap_
6 |
7 | # files for the dex VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # generated files - android project subfolder
14 | Android/bin/
15 | Android/gen/
16 | Android/assets/
17 |
18 | # generated files
19 | bin/
20 | gen/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # IOS / Xcode
26 | build/*
27 | *.pbxuser
28 | !default.pbxuser
29 | *.mode1v3
30 | !default.mode1v3
31 | *.mode2v3
32 | !default.mode2v3
33 | *.perspectivev3
34 | !default.perspectivev3
35 | *.xcworkspace
36 | !default.xcworkspace
37 | xcuserdata
38 | profile
39 | *.moved-aside
40 | IOS/www/
41 |
42 | # OSX
43 | .DS_Store
44 |
45 | # Thumbnails
46 | ._*
47 |
48 | # Files that might appear on external disk
49 | .Spotlight-V100
50 | .Trashes
--------------------------------------------------------------------------------
/cordova/BOOM.bat:
--------------------------------------------------------------------------------
1 | :: Licensed to the Apache Software Foundation (ASF) under one
2 | :: or more contributor license agreements. See the NOTICE file
3 | :: distributed with this work for additional information
4 | :: regarding copyright ownership. The ASF licenses this file
5 | :: to you under the Apache License, Version 2.0 (the
6 | :: "License"); you may not use this file except in compliance
7 | :: with the License. You may obtain a copy of the License at
8 | ::
9 | :: http://www.apache.org/licenses/LICENSE-2.0
10 | ::
11 | :: Unless required by applicable law or agreed to in writing,
12 | :: software distributed under the License is distributed on an
13 | :: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | :: KIND, either express or implied. See the License for the
15 | :: specific language governing permissions and limitations
16 | :: under the License.
17 |
18 | %~dp0\cordova.bat BOOM
19 |
--------------------------------------------------------------------------------
/cordova/log.bat:
--------------------------------------------------------------------------------
1 | :: Licensed to the Apache Software Foundation (ASF) under one
2 | :: or more contributor license agreements. See the NOTICE file
3 | :: distributed with this work for additional information
4 | :: regarding copyright ownership. The ASF licenses this file
5 | :: to you under the Apache License, Version 2.0 (the
6 | :: "License"); you may not use this file except in compliance
7 | :: with the License. You may obtain a copy of the License at
8 | ::
9 | :: http://www.apache.org/licenses/LICENSE-2.0
10 | ::
11 | :: Unless required by applicable law or agreed to in writing,
12 | :: software distributed under the License is distributed on an
13 | :: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | :: KIND, either express or implied. See the License for the
15 | :: specific language governing permissions and limitations
16 | :: under the License.
17 |
18 | %~dp0\cordova.bat log
19 |
--------------------------------------------------------------------------------
/cordova/clean.bat:
--------------------------------------------------------------------------------
1 | :: Licensed to the Apache Software Foundation (ASF) under one
2 | :: or more contributor license agreements. See the NOTICE file
3 | :: distributed with this work for additional information
4 | :: regarding copyright ownership. The ASF licenses this file
5 | :: to you under the Apache License, Version 2.0 (the
6 | :: "License"); you may not use this file except in compliance
7 | :: with the License. You may obtain a copy of the License at
8 | ::
9 | :: http://www.apache.org/licenses/LICENSE-2.0
10 | ::
11 | :: Unless required by applicable law or agreed to in writing,
12 | :: software distributed under the License is distributed on an
13 | :: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | :: KIND, either express or implied. See the License for the
15 | :: specific language governing permissions and limitations
16 | :: under the License.
17 |
18 | %~dp0\cordova.bat clean
19 |
--------------------------------------------------------------------------------
/cordova/debug.bat:
--------------------------------------------------------------------------------
1 | :: Licensed to the Apache Software Foundation (ASF) under one
2 | :: or more contributor license agreements. See the NOTICE file
3 | :: distributed with this work for additional information
4 | :: regarding copyright ownership. The ASF licenses this file
5 | :: to you under the Apache License, Version 2.0 (the
6 | :: "License"); you may not use this file except in compliance
7 | :: with the License. You may obtain a copy of the License at
8 | ::
9 | :: http://www.apache.org/licenses/LICENSE-2.0
10 | ::
11 | :: Unless required by applicable law or agreed to in writing,
12 | :: software distributed under the License is distributed on an
13 | :: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | :: KIND, either express or implied. See the License for the
15 | :: specific language governing permissions and limitations
16 | :: under the License.
17 |
18 | %~dp0\cordova.bat debug
19 |
--------------------------------------------------------------------------------
/assets/www/media/css/style/login.less:
--------------------------------------------------------------------------------
1 | .lcb-view-login {
2 | .content {
3 | background-image: url('../img/maze.png');
4 | }
5 | button {
6 | width: 100%;
7 | }
8 | .response {
9 | background-color: #fcf8e3;
10 | color: #c09853;
11 | text-align: center;
12 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
13 | padding: 10px;
14 | margin-bottom: 10px;
15 | border: 1px solid #fbeed5;
16 | .border-radius(4px);
17 | &:empty {
18 | display: none;
19 | }
20 | &.error {
21 | color: #b94a48;
22 | background-color: #f2dede;
23 | border-color: #eed3d7;
24 | }
25 | &.success {
26 | color: #468847;
27 | background-color: #dff0d8;
28 | border-color: #d6e9c6;
29 | }
30 | }
31 | .build {
32 | text-align: center;
33 | font-size: 12px;
34 | }
35 | }
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | LetsChat
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/assets/www/media/css/style/base.less:
--------------------------------------------------------------------------------
1 | body {
2 | width: 100%;
3 | font-size: 1em;
4 | }
5 |
6 | @font-face {
7 | font-family: 'Pacifico';
8 | src: url('../font/Pacifico-webfont.eot');
9 | src: url('../font/Pacifico-webfont.eot?#iefix') format('embedded-opentype'),
10 | url('../font/Pacifico-webfont.woff') format('woff'),
11 | url('../font/Pacifico-webfont.ttf') format('truetype'),
12 | url('../font/Pacifico-webfont.svg#PacificoRegular') format('svg');
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
17 | .view {
18 | display: none;
19 | }
20 |
21 | .view.current {
22 | display: block;
23 | }
24 |
25 | // Fixes android viewport issue
26 | @media (orientation:portrait) and (orientation:landscape) {
27 | .content,
28 | .bar-title {
29 | position:fixed;
30 | }
31 | }
32 |
33 | .bar-title .title {
34 | text-align: center;
35 | font-family: 'Pacifico';
36 | }
37 |
38 | .count:empty {
39 | display: none;
40 | }
--------------------------------------------------------------------------------
/cordova/cordova.bat:
--------------------------------------------------------------------------------
1 | :: Licensed to the Apache Software Foundation (ASF) under one
2 | :: or more contributor license agreements. See the NOTICE file
3 | :: distributed with this work for additional information
4 | :: regarding copyright ownership. The ASF licenses this file
5 | :: to you under the Apache License, Version 2.0 (the
6 | :: "License"); you may not use this file except in compliance
7 | :: with the License. You may obtain a copy of the License at
8 | ::
9 | :: http://www.apache.org/licenses/LICENSE-2.0
10 | ::
11 | :: Unless required by applicable law or agreed to in writing,
12 | :: software distributed under the License is distributed on an
13 | :: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | :: KIND, either express or implied. See the License for the
15 | :: specific language governing permissions and limitations
16 | :: under the License.
17 |
18 | @ECHO OFF
19 | IF NOT DEFINED JAVA_HOME GOTO MISSING
20 | FOR %%X in (java.exe ant.bat android.bat) do (
21 | SET FOUND=%%~$PATH:X
22 | IF NOT DEFINED FOUND GOTO MISSING
23 | )
24 | cscript %~dp0\cordova.js %*
25 | GOTO END
26 | :MISSING
27 | ECHO Missing one of the following:
28 | ECHO JDK: http://java.oracle.com
29 | ECHO Android SDK: http://developer.android.com
30 | ECHO Apache ant: http://ant.apache.org
31 | EXIT /B 1
32 | :END
33 |
--------------------------------------------------------------------------------
/src/com/LetsChat/LetsChat.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | package com.LetsChat;
21 |
22 | import android.app.Activity;
23 | import android.os.Bundle;
24 | import org.apache.cordova.*;
25 |
26 | public class LetsChat extends DroidGap
27 | {
28 | @Override
29 | public void onCreate(Bundle savedInstanceState)
30 | {
31 | super.onCreate(savedInstanceState);
32 | super.loadUrl("file:///android_asset/www/index.html");
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/com/phonegap/plugins/statusBarNotification/StatusNotificationIntent.java:
--------------------------------------------------------------------------------
1 | // This class is used on all Androids below Honeycomb
2 | package com.phonegap.plugins.statusBarNotification;
3 |
4 |
5 | import android.app.Notification;
6 | import android.app.PendingIntent;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.pm.PackageManager;
10 |
11 | import com.LetsChat.R;
12 |
13 | public class StatusNotificationIntent {
14 | public static Notification buildNotification( Context context, CharSequence tag, CharSequence contentTitle, CharSequence contentText, int flag ) {
15 | int icon = R.drawable.notification;
16 | long when = System.currentTimeMillis();
17 | Notification noti = new Notification(icon, contentTitle, when);
18 | noti.flags |= flag;
19 |
20 | PackageManager pm = context.getPackageManager();
21 | Intent notificationIntent = pm.getLaunchIntentForPackage(context.getPackageName());
22 | notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
23 | notificationIntent.putExtra("notificationTag", tag);
24 |
25 | PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
26 | noti.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
27 | return noti;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/assets/www/media/js/util/message.js:
--------------------------------------------------------------------------------
1 |
2 | if (typeof window !== 'undefined' && typeof exports === 'undefined') {
3 | if (typeof window.utils !== 'object') window.utils = {};
4 | }
5 |
6 | if (typeof exports !== 'undefined') {
7 | var _ = require('underscore');
8 | }
9 |
10 | (function(exports) {
11 | //
12 | // Message Text Formatting
13 | //
14 | exports.format = function(text, plugins, mention) {
15 | // TODO: Fix these regexes
16 | var imagePattern = /((https?|ftp):\/\/[^\s\/$.?#].[^\s]*[.](jpe?g|png|gif)\s*$)/gi;
17 | var linkPattern = /((https?|ftp):\/\/[^\s\/$.?#].[^\s]*[^.])/gi;
18 | if (text.match(imagePattern)) {
19 | text = text.replace(imagePattern, '
');
20 | } else {
21 | text = text.replace(linkPattern, '$1');
22 | }
23 | if (plugins) {
24 | // emotes
25 | _.each(plugins.emotes, function(emote, keyword) {
26 | var image = '
';
27 | text = text.replace(new RegExp('\\B' + keyword + '\\b', 'g'), image);
28 | });
29 | // replacements
30 | _.each(plugins.replacements, function(replacement) {
31 | text = text.replace(new RegExp(replacement.regex, 'g'), replacement.template);
32 | });
33 | }
34 | if (mention) {
35 | text = text.replace(new RegExp('(\\@' + mention + '\\b)', 'ig'), '$1')
36 | }
37 | return text;
38 | }
39 | })(typeof exports === 'undefined' ? window.utils.message = {} : exports);
--------------------------------------------------------------------------------
/assets/www/media/css/style/chat.less:
--------------------------------------------------------------------------------
1 | .room-item {
2 | &:active {
3 | background: red;
4 | color: #fff;
5 | }
6 | }
7 |
8 | .messages {
9 | word-wrap: break-word;
10 | position: fixed;
11 | top: 44px;
12 | right: 0;
13 | bottom: 44px;
14 | left: 0;
15 | overflow: auto;
16 | padding: 0;
17 | margin: 0;
18 | }
19 |
20 | .message {
21 | background: #f2f2f2;
22 | border-bottom: 1px #eee solid;
23 | position: relative;
24 | .top {
25 | margin-left: 2px;
26 | }
27 | .name {
28 | font-weight: bold;
29 | color: #aaa;
30 | }
31 | .time {
32 | color: #bbb;
33 | }
34 | .avatar {
35 | width: 51px;
36 | height: 51px;
37 | margin-top: -1px;
38 | position: absolute;
39 | }
40 | .meta {
41 | background: #fff;
42 | min-height: 44px;
43 | padding: 3px 5px;
44 | margin-left: 51px;
45 | }
46 | .mention {
47 | font-weight: bold;
48 | color: #f22472;
49 | }
50 | .fragments {
51 | padding: 2px;
52 | }
53 | .fragment {
54 | padding: 2px;
55 | }
56 | .text {
57 | img {
58 | max-width: 100%;
59 | }
60 | }
61 | &.own {
62 | .avatar {
63 | right: 0;
64 | }
65 | .meta {
66 | text-align: right;
67 | margin-left: auto;
68 | margin-right: 51px;
69 | }
70 | }
71 | }
72 |
73 | .entry {
74 | padding: 0;
75 | box-shadow: 0 0 15px #bbb;
76 | display: -webkit-box;
77 | display: box;
78 | -webkit-box-orient: horizontal;
79 | box-orient: horizontal;
80 | &, input, button {
81 | display: -webkit-box;
82 | display: box;
83 | }
84 | input {
85 | width: auto;
86 | border: none;
87 | -webkit-box-shadow: none;
88 | box-shadow: none;
89 | -webkit-box-flex: 1;
90 | box-flex: 1;
91 | }
92 | .button {
93 | height: 100%;
94 | line-height: 30px;
95 | font-size: 22px;
96 | border-top: none;
97 | border-right: none;
98 | border-left-color: #ddd;
99 | border-radius: 0;
100 | -webkit-border-radius: 0;
101 | i {
102 | vertical-align: middle;
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/assets/www/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
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 |
--------------------------------------------------------------------------------
/res/xml/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
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 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
22 |
30 |
45 |
46 |
47 |
48 |
49 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/assets/www/media/js/vendor/toe.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * toe.js
3 | * version 2.0.0
4 | * author: Damien Antipa
5 | * https://github.com/dantipa/toe.js
6 | */
7 | (function(t){var n={Event:function(n){var e={timestamp:(new Date).getTime(),target:n.target,point:[]},a=n.changedTouches||n.originalEvent.changedTouches||n.touches||n.originalEvent.touches;return t.each(a,function(t,n){e.point.push({x:n.pageX,y:n.pageY})}),e},State:function(t){var n=t.point[0];return{start:t,move:[],end:null,pageX:n.x,pageY:n.y}},track:function(e){var a,o=function(t){var o=n.Event(t);a=n.State(o),e.touchstart(t,a,o)},i=function(t){var o=n.Event(t);a.move.push(o),e.touchmove(t,a,o)},r=function(t){var o=n.Event(t);a.end=o,e.touchend(t,a,o)};return e.setup=function(n){t(this).on("touchstart",n,o).on("touchmove",n,i).on("touchend touchcancel",n,r)},e.teardown=function(){t(this).off("touchstart",o).off("touchmove",i).off("touchend touchcancel",r)},e},calc:{getDuration:function(t,n){return n.timestamp-t.timestamp},getDistance:function(t,n){return Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2))},getAngle:function(t,n){return 180*Math.atan2(n.y-t.y,n.x-t.x)/Math.PI},getDirection:function(t){return-45>t&&t>-135?"top":t>=-45&&45>=t?"right":t>=45&&135>t?"down":t>=135||-135>=t?"left":"unknown"},getScale:function(t,n){var e=t.point,a=n.point;return 2===e.length&&2===a.length?(Math.sqrt(Math.pow(a[0].x-a[1].x,2)+Math.pow(a[0].y-a[1].y,2))/Math.sqrt(Math.pow(e[0].x-e[1].x,2)+Math.pow(e[0].y-e[1].y,2))).toFixed(2):0},getRotation:function(t,n){var e=t.point,a=n.point;return 2===e.length&&2===a.length?(180*Math.atan2(a[0].y-a[1].y,a[0].x-a[1].x)/Math.PI-180*Math.atan2(e[0].y-e[1].y,e[0].x-e[1].x)/Math.PI).toFixed(2):0}}};t.toe=n})(jQuery,this),function(t,n){t.event.special.swipe=function(){var e={distance:40,duration:300,direction:"all",finger:1};return n.track({touchstart:function(t,n){n.finger=n.start.point.length},touchmove:function(t,n,e){n.finger=e.point.length>n.finger?e.point.length:n.finger},touchend:function(a,o,i){var r,c,u=t.extend(e,a.data);r=n.calc.getDuration(o.start,i),c=n.calc.getDistance(o.start.point[0],i.point[0]),u.duration>r&&c>u.distance&&(o.angle=n.calc.getAngle(o.start.point[0],i.point[0]),o.direction=n.calc.getDirection(o.angle),o.finger!==u.finger||"all"!==u.direction&&o.direction!==u.direction||t(a.target).trigger(t.Event("swipe",o)))}})}()}(jQuery,jQuery.toe,this),function(t,n){t.event.special.tap=function(){var e={distance:10,duration:300,finger:1};return n.track({touchstart:function(t,n,e){n.finger=e.point.length},touchmove:function(t,n,e){n.finger=e.point.length>n.finger?e.point.length:n.finger},touchend:function(a,o,i){var r,c,u=t.extend(e,a.data);r=n.calc.getDuration(o.start,i),c=n.calc.getDistance(o.start.point[0],i.point[0]),u.duration>r&&u.distance>c&&o.finger===u.finger&&t(a.target).trigger(t.Event("tap",o))}})}()}(jQuery,jQuery.toe,this),function(t,n){t.event.special.taphold=function(){var e,a,o={distance:20,duration:500,finger:1};return n.track({touchstart:function(n,i,r){var c=t.extend(o,n.data);a=!1,i.finger=r.point.length,clearTimeout(e),e=setTimeout(function(){a||i.finger===c.finger&&t(n.target).trigger(t.Event("taphold",i))},c.duration)},touchmove:function(e,i,r){var c,u=t.extend(o,e.data);i.finger=r.point.length>i.finger?r.point.length:i.finger,c=n.calc.getDistance(i.start.point[0],r.point[0]),c>u.distance&&(a=!0)},touchend:function(){a=!0,clearTimeout(e)}})}()}(jQuery,jQuery.toe,this),function(t,n){t.event.special.transform=function(){var e,a={scale:.1,rotation:15};return n.track({touchstart:function(){e=!1},touchmove:function(o,i,r){var c=t.extend(a,o.data);return 2!==r.point.length?(i.move.pop(),undefined):(2!==i.start.point.length&&2===r.point.length&&(i.start=t.extend({},r)),i.rotation=n.calc.getRotation(i.start,r),i.scale=n.calc.getScale(i.start,r),(Math.abs(1-i.scale)>c.scale||Math.abs(i.rotation)>c.rotation)&&(e||(t(o.target).trigger(t.Event("transformstart",i)),e=!0),t(o.target).trigger(t.Event("transform",i))),undefined)},touchend:function(a,o,i){e&&(e=!1,2!==i.point.length&&(o.end=t.extend({},o.move[o.move.length-1])),o.rotation=n.calc.getRotation(o.start,o.end),o.scale=n.calc.getScale(o.start,o.end),t(a.target).trigger(t.Event("transformend",o)))}})}()}(jQuery,jQuery.toe,this);
--------------------------------------------------------------------------------
/cordova/cordova.js:
--------------------------------------------------------------------------------
1 | // Licensed to the Apache Software Foundation (ASF) under one
2 | // or more contributor license agreements. See the NOTICE file
3 | // distributed with this work for additional information
4 | // regarding copyright ownership. The ASF licenses this file
5 | // to you under the Apache License, Version 2.0 (the
6 | // "License"); you may not use this file except in compliance
7 | // with the License. You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing,
12 | // software distributed under the License is distributed on an
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | // KIND, either express or implied. See the License for the
15 | // specific language governing permissions and limitations
16 | // under the License.
17 |
18 | var ROOT = WScript.ScriptFullName.split('\\cordova\\cordova.js').join(''),
19 | shell=WScript.CreateObject("WScript.Shell");
20 |
21 | function exec(command) {
22 | var oExec=shell.Exec(command);
23 | var output = new String();
24 | while(oExec.Status == 0) {
25 | if(!oExec.StdOut.AtEndOfStream) {
26 | var line = oExec.StdOut.ReadLine();
27 | // XXX: Change to verbose mode
28 | // WScript.StdOut.WriteLine(line);
29 | output += line;
30 | }
31 | WScript.sleep(100);
32 | }
33 |
34 | return output;
35 | }
36 |
37 | function emulator_running() {
38 | var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
39 | if(local_devices.match(/emulator/)) {
40 | return true;
41 | }
42 | return false;
43 | }
44 | function emulate() {
45 | // don't run emulator if a device is plugged in or if emulator is already running
46 | if(emulator_running()) {
47 | WScript.Echo("Device or Emulator already running!");
48 | return;
49 | }
50 | var oExec = shell.Exec("%comspec% /c android.bat list avd");
51 | var avd_list = [];
52 | var avd_id = -10;
53 | while(!oExec.StdOut.AtEndOfStream) {
54 | var output = oExec.StdOut.ReadLine();
55 | if(output.match(/Name: (.)*/)) {
56 | avd_list.push(output.replace(/ *Name:\s/, ""));
57 | }
58 | }
59 | // user has no AVDs
60 | if(avd_list.length == 0) {
61 | WScript.Echo("You don't have any Android Virtual Devices. Please create at least one AVD.");
62 | WScript.Echo("android");
63 | WScript.Quit(1);
64 | }
65 | // user has only one AVD so we launch that one
66 | if(avd_list.length == 1) {
67 |
68 | shell.Run("emulator -cpu-delay 0 -no-boot-anim -cache %Temp%\cache -avd "+avd_list[0]);
69 | }
70 |
71 | // user has more than one avd so we ask them to choose
72 | if(avd_list.length > 1) {
73 | while(!avd_list[avd_id]) {
74 | WScript.Echo("Choose from one of the following Android Virtual Devices [0 to "+(avd_list.length - 1)+"]:")
75 | for(i = 0, j = avd_list.length ; i < j ; i++) {
76 | WScript.Echo((i)+") "+avd_list[i]);
77 | }
78 | WScript.StdOut.Write("> ");
79 | avd_id = new Number(WScript.StdIn.ReadLine());
80 | }
81 |
82 | shell.Run("emulator -cpu-delay 0 -no-boot-anim -cache %Temp%\\cache -avd "+avd_list[avd_id], 0, false);
83 | }
84 | }
85 |
86 | function clean() {
87 | exec("%comspec% /c ant.bat clean -f "+ROOT+"\\build.xml 2>&1");
88 | }
89 |
90 | function debug() {
91 | if(emulator_running()) {
92 | exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
93 | } else {
94 | exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
95 | WScript.Echo("##################################################################");
96 | WScript.Echo("# Plug in your device or launch an emulator with cordova/emulate #");
97 | WScript.Echo("##################################################################");
98 | }
99 | }
100 |
101 | function log() {
102 | shell.Run("%comspec% /c adb logcat");
103 | }
104 |
105 | function launch() {
106 | var launch_str=exec("%comspec% /c java -jar "+ROOT+"\\cordova\\appinfo.jar "+ROOT+"\\AndroidManifest.xml");
107 | //WScript.Echo(launch_str);
108 | exec("%comspec% /c adb shell am start -n "+launch_str+" 2>&1");
109 | }
110 |
111 | function BOOM() {
112 | clean();
113 | debug();
114 | launch();
115 | }
116 | var args = WScript.Arguments;
117 | if(args.count() != 1) {
118 | WScript.StdErr.Write("An error has occured!\n");
119 | WScript.Quit(1);
120 | }
121 | eval(args(0)+"()");
122 |
--------------------------------------------------------------------------------
/assets/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Let's Chat
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Let's Chat
30 |
31 |
32 |
53 |
54 |
55 |
56 |
57 |
58 | Rooms
59 |
60 |
61 |
64 |
65 |
66 |
67 |
76 |
92 |
104 |
109 |
--------------------------------------------------------------------------------
/assets/www/media/js/vendor/statusbarnotification.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (C) 2011 Dmitry Savchenko
4 | *
5 | * Permission is hereby granted, free of charge, to any person
6 | * obtaining a copy of this software and associated documentation
7 | * files (the "Software"), to deal in the Software without
8 | * restriction, including without limitation the rights to use,
9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the
11 | * Software is furnished to do so, subject to the following
12 | * conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | * OTHER DEALINGS IN THE SOFTWARE.
25 | *
26 | */
27 |
28 | var cordovaRef = window.PhoneGap || window.Cordova || window.cordova; // old to new fallbacks
29 |
30 | /**
31 | * Flags to denote the Android Notification constants
32 | * Values are representation from Android Notification Flag bit vals
33 | */
34 |
35 | function Flag() {}
36 | Flag.FLAG_AUTO_CANCEL="16";
37 | Flag.FLAG_NO_CLEAR="32";
38 |
39 | /** @deprecated Use the W3C standard window.Notification API instead. */
40 | var NotificationMessenger = function() { }
41 |
42 | /**
43 | * @param title Title of the notification
44 | * @param body Body of the notification
45 | * @deprecated Use the W3C standard window.Notification API instead.
46 | */
47 | NotificationMessenger.prototype.notify = function(title, body, flag) {
48 | if (window.Notification) {
49 | this.activeNotification = new window.Notification(title, {
50 | body: body,
51 | flag: flag
52 | });
53 | }
54 | }
55 |
56 | /**
57 | * Clears the Notificaiton Bar
58 | * @deprecated Use the W3C standard window.Notification API instead.
59 | */
60 | NotificationMessenger.prototype.clear = function() {
61 | if (this.activeNotification) {
62 | this.activeNotification.close();
63 | this.activeNotification = undefined;
64 | }
65 | }
66 |
67 | if (!window.plugins) window.plugins = {}
68 | if (!window.plugins.statusBarNotification) window.plugins.statusBarNotification = new NotificationMessenger();
69 |
70 |
71 | /*
72 | * The W3C standard API, window.Notification. See http://www.w3.org/TR/notifications/
73 | * This API should be used for new applications instead of the old plugin API above.
74 | */
75 | if (typeof window.Notification == 'undefined') {
76 |
77 | /**
78 | * Creates and shows a new notification.
79 | * @param title
80 | * @param options
81 | */
82 | window.Notification = function(title, options) {
83 | options = options || {};
84 | this.tag = options.tag || 'defaultTag';
85 |
86 | // Add this notification to the global index by tag.
87 | window.Notification.active[this.tag] = this;
88 |
89 | // May be undefined.
90 | this.onclick = options.onclick;
91 | this.onerror = options.onerror;
92 | this.onshow = options.onshow;
93 | this.onclose = options.onclose;
94 |
95 | var content = options.body || '';
96 |
97 | var flag = options.flag || '';
98 |
99 | cordova.exec(function() {
100 | if (this.onshow) {
101 | this.onshow();
102 | }
103 | }, function(error) {
104 | if (this.onerror) {
105 | this.onerror(error);
106 | }
107 | }, 'StatusBarNotification', 'notify', [this.tag, title, content, flag]);
108 | };
109 |
110 | // Permission is always granted on Android.
111 | window.Notification.permission = 'granted';
112 |
113 | window.Notification.requestPermission = function(callback) {
114 | callback('granted');
115 | };
116 |
117 | // Not part of the W3C API. Used by the native side to call onclick handlers.
118 | window.Notification.callOnclickByTag = function(tag) {
119 | console.log('callOnclickByTag');
120 | var notification = window.Notification.active[tag];
121 | if (notification && notification.onclick && typeof notification.onclick == 'function') {
122 | console.log('inside if');
123 | notification.onclick();
124 | }
125 | };
126 |
127 | // A global map of notifications by tag, so their onclick callbacks can be called.
128 | window.Notification.active = {};
129 |
130 |
131 | /**
132 | * Cancels a notification that has already been created and shown to the user.
133 | */
134 | window.Notification.prototype.close = function() {
135 | cordova.exec(function() {
136 | if (this.onclose) {
137 | this.onclose();
138 | }
139 | }, function(error) {
140 | if (this.onerror) {
141 | this.onerror(error);
142 | }
143 | }, 'StatusBarNotification', 'clear', [this.tag]);
144 | };
145 | }
146 |
147 | // vim: tabstop=4:softtabstop=4:shiftwidth=4:expandtab
148 |
--------------------------------------------------------------------------------
/src/com/phonegap/plugins/statusBarNotification/StatusBarNotification.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (C) 2011 Dmitry Savchenko
4 | *
5 | * Permission is hereby granted, free of charge, to any person
6 | * obtaining a copy of this software and associated documentation
7 | * files (the "Software"), to deal in the Software without
8 | * restriction, including without limitation the rights to use,
9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the
11 | * Software is furnished to do so, subject to the following
12 | * conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | * OTHER DEALINGS IN THE SOFTWARE.
25 | *
26 | */
27 |
28 | package com.phonegap.plugins.statusBarNotification;
29 |
30 | import org.apache.cordova.api.CallbackContext;
31 | import org.apache.cordova.api.CordovaPlugin;
32 | import org.json.JSONArray;
33 | import org.json.JSONException;
34 |
35 | import android.app.Notification;
36 | import android.app.NotificationManager;
37 | import android.content.Context;
38 | import android.content.Intent;
39 | import android.util.Log;
40 |
41 | public class StatusBarNotification extends CordovaPlugin {
42 | // Action to execute
43 | public static final String NOTIFY = "notify";
44 | public static final String CLEAR = "clear";
45 |
46 | /**
47 | * Executes the request and returns PluginResult
48 | *
49 | * @param action Action to execute
50 | * @param data JSONArray of arguments to the plugin
51 | * @param callbackContext The callback context used when calling back into JavaScript.
52 | *
53 | * @return A PluginRequest object with a status
54 | * */
55 | @Override
56 | public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {
57 | boolean actionValid = true;
58 | if (NOTIFY.equals(action)) {
59 | try {
60 | String tag = data.getString(0);
61 | String title = data.getString(1);
62 | String body = data.getString(2);
63 | String flag = data.getString(3);
64 | Log.d("NotificationPlugin", "Notification: " + tag + ", " + title + ", " + body);
65 | int notificationFlag = getFlagValue(flag);
66 | showNotification(tag, title, body, notificationFlag);
67 | } catch (JSONException jsonEx) {
68 | Log.d("NotificationPlugin", "Got JSON Exception "
69 | + jsonEx.getMessage());
70 | actionValid = false;
71 | }
72 | } else if (CLEAR.equals(action)){
73 | try {
74 | String tag = data.getString(0);
75 | Log.d("NotificationPlugin", "Notification cancel: " + tag);
76 | clearNotification(tag);
77 | } catch (JSONException jsonEx) {
78 | Log.d("NotificationPlugin", "Got JSON Exception " + jsonEx.getMessage());
79 | actionValid = false;
80 | }
81 | } else {
82 | actionValid = false;
83 | Log.d("NotificationPlugin", "Invalid action : "+action+" passed");
84 | }
85 | return actionValid;
86 | }
87 |
88 | /**
89 | * Helper method that returns a flag value to be used for notification
90 | * by default it will return 16 representing FLAG_NO_CLEAR
91 | *
92 | * @param flag
93 | * @return int value of the flag
94 | */
95 | private int getFlagValue(String flag) {
96 | int flagVal = Notification.FLAG_AUTO_CANCEL;
97 |
98 | // We trust the flag value as it comes from our JS constant.
99 | // This is also backwards compatible as it will be emtpy.
100 | if (!flag.isEmpty()){
101 | flagVal = Integer.parseInt(flag);
102 | }
103 |
104 | return flagVal;
105 | }
106 |
107 | /**
108 | * Displays status bar notification
109 | *
110 | * @param tag Notification tag.
111 | * @param contentTitle Notification title
112 | * @param contentText Notification text
113 | * */
114 | public void showNotification( CharSequence tag, CharSequence contentTitle, CharSequence contentText, int flag) {
115 | String ns = Context.NOTIFICATION_SERVICE;
116 | context = cordova.getActivity().getApplicationContext();
117 | mNotificationManager = (NotificationManager) context.getSystemService(ns);
118 |
119 | Notification noti = StatusNotificationIntent.buildNotification(context, tag, contentTitle, contentText, flag);
120 | mNotificationManager.notify(tag.hashCode(), noti);
121 | }
122 |
123 | /**
124 | * Cancels a single notification by tag.
125 | *
126 | * @param tag Notification tag to cancel.
127 | */
128 | public void clearNotification(String tag) {
129 | mNotificationManager.cancel(tag.hashCode());
130 | }
131 |
132 | /**
133 | * Removes all Notifications from the status bar.
134 | */
135 | public void clearAllNotifications() {
136 | mNotificationManager.cancelAll();
137 | }
138 |
139 | /**
140 | * Called when a notification is clicked.
141 | * @param intent The new Intent passed from the notification.
142 | */
143 | @Override
144 | public void onNewIntent(Intent intent) {
145 | // The incoming Intent may or may not have been for a notification.
146 | String tag = intent.getStringExtra("notificationTag");
147 | if (tag != null) {
148 | this.webView.sendJavascript("window.Notification.callOnclickByTag('"+ tag + "')");
149 | }
150 | }
151 |
152 |
153 | private NotificationManager mNotificationManager;
154 | private Context context;
155 | }
156 |
--------------------------------------------------------------------------------
/assets/www/media/js/client.js:
--------------------------------------------------------------------------------
1 | function Client() {};
2 |
3 | Client.prototype.init = function() {
4 | var client = this;
5 | this.state = {};
6 | this.events = _.extend({}, Backbone.Events);
7 | this.data = {
8 | user: new UserModel,
9 | rooms: new RoomsCollection
10 | }
11 | this.view = new ClientView({
12 | client: this
13 | });
14 | this.listenGUI();
15 | this.route();
16 | };
17 |
18 | Client.prototype.route = function() {
19 | var self = this;
20 | var Router = Backbone.Router.extend({
21 | routes: {
22 | '!/rooms': 'rooms',
23 | '!/room/:id': 'room',
24 | '*path': 'login'
25 | },
26 | login: function() {
27 | if (self.state.authenticated) {
28 | this.navigate('!/rooms');
29 | return;
30 | }
31 | self.events.trigger('views:show', 'login');
32 | },
33 | rooms: function() {
34 | if (!self.state.authenticated) {
35 | this.navigate('!/', true);
36 | return;
37 | }
38 | self.events.trigger('views:show', 'room-list');
39 | },
40 | room: function(id) {
41 | if (!self.state.authenticated) {
42 | this.navigate('!/', true);
43 | return;
44 | }
45 | self.events.trigger('views:show', id);
46 | }
47 | });
48 | this.router = new Router;
49 | Backbone.history.start();
50 | };
51 |
52 | Client.prototype.listenGUI = function() {
53 | var self = this;
54 | this.events.on('client:pause', function() {
55 | self.state.paused = true;
56 | });
57 | this.events.on('client:resume', function() {
58 | self.state.paused = false;
59 | });
60 | this.events.on('client:login', this.login, this);
61 | this.events.on('room:message:send', function(message) {
62 | self.socket.emit('room:messages:new', message);
63 | });
64 | this.events.on('room:message:new', function(message) {
65 | if (!client.state.paused) {
66 | return;
67 | }
68 | if (message.text.match(new RegExp('\\@' + self.data.user.get('safeName') + '\\b', 'g'))) {
69 | console.log(message.text.match(new RegExp('\\@' + self.data.user.get('safeName') + '\\b', 'ig')));
70 | window.plugins.statusBarNotification.notify('Mentioned by ' + message.name, message.text);
71 | }
72 | })
73 | };
74 |
75 | Client.prototype.listenSocket = function() {
76 | var self = this;
77 | if (this.state.listenSocket) {
78 | return;
79 | }
80 | this.socket.on('connect', function() {
81 | self.socket.emit('user:whoami');
82 | self.socket.emit('rooms:get');
83 | });
84 | this.socket.on('user:whoami', function(profile) {
85 | self.data.user.set(profile);
86 | });
87 | this.socket.on('user:update', function(profile) {
88 | });
89 | this.socket.on('room:messages:new', function(data) {
90 | if ($.isArray(data)) {
91 | _.each(data, function(message) {
92 | var room = self.data.rooms.get(message.room);
93 | room.messages.add(message, {
94 | silent: true
95 | });
96 | room.messages.trigger('addsoftly', message);
97 | });
98 | } else {
99 | var room = self.data.rooms.get(data.room);
100 | room.messages.add(data);
101 | self.events.trigger('room:message:new', data);
102 | }
103 | });
104 | this.socket.on('room:users:new', function(user) {
105 | });
106 | this.socket.on('room:users:leave', function(user) {
107 | });
108 | this.socket.on('room:remove', function(id) {
109 | });
110 | this.socket.on('room:update', function(data) {
111 | });
112 | this.socket.on('rooms:new', function(room) {
113 | self.data.rooms.add(room);
114 | self.socket.emit('room:join', room.id);
115 | self.socket.emit('room:messages:get', {
116 | room: room.id
117 | });
118 | });
119 | this.socket.on('rooms:remove', function(id) {
120 | self.data.rooms.remove(id);
121 | });
122 | this.socket.on('rooms:users:new', function(user) {
123 | });
124 | this.socket.on('rooms:users:leave', function(user) {
125 | });
126 | this.state.listenSocket = true;
127 | };
128 |
129 | Client.prototype.login = function(creds) {
130 | var self = this;
131 | store.set('config', {
132 | url: creds.url,
133 | username: creds.username
134 | });
135 | try {
136 | var connectionURL = URI(creds.url).search({
137 | username: creds.username,
138 | password: creds.password
139 | });
140 | if (!connectionURL.is('url') || !connectionURL.is('absolute')) {
141 | throw 'Invalid URL';
142 | }
143 | this.connect(connectionURL.toString(), true);
144 | this.socket.once('error', function(err) {
145 | self.state.authenticated = false;
146 | self.events.trigger('client:login:error', err || 'Connection failed');
147 | });
148 | this.socket.once('connect', function() {
149 | self.state.authenticated = true;
150 | self.connect(connectionURL.toString(), false);
151 | self.events.trigger('client:login:success');
152 | self.router.navigate('!/rooms', true);
153 | });
154 | } catch(e) {
155 | this.events.trigger('client:login:error', e);
156 | }
157 | };
158 |
159 | Client.prototype.connect = function(url, once) {
160 | if (once) {
161 | this.disconnect();
162 | this.socket = io.connect(url, {
163 | reconnect: true,
164 | 'force new connection': true
165 | });
166 | this.socket.once('connect', function() {
167 | this.disconnect();
168 | })
169 | return;
170 | }
171 | this.socket = io.connect(url, {
172 | reconnect: true,
173 | 'force new connection': false
174 | });
175 | this.listenSocket();
176 | }
177 |
178 | Client.prototype.disconnect = function() {
179 | if (this.socket && this.socket.socket.connected) {
180 | this.socket.disconnect();
181 | return true;
182 | }
183 | return false;
184 | };
185 |
186 | $(function() {
187 | window.client = new Client;
188 | window.client.init();
189 | });
--------------------------------------------------------------------------------
/assets/www/media/js/vendor/store.js:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2010-2012 Marcus Westin
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | * THE SOFTWARE.
20 | */
21 |
22 | ;(function(){
23 | var store = {},
24 | win = window,
25 | doc = win.document,
26 | localStorageName = 'localStorage',
27 | globalStorageName = 'globalStorage',
28 | namespace = '__storejs__',
29 | storage
30 |
31 | store.disabled = false
32 | store.set = function(key, value) {}
33 | store.get = function(key) {}
34 | store.remove = function(key) {}
35 | store.clear = function() {}
36 | store.transact = function(key, defaultVal, transactionFn) {
37 | var val = store.get(key)
38 | if (transactionFn == null) {
39 | transactionFn = defaultVal
40 | defaultVal = null
41 | }
42 | if (typeof val == 'undefined') { val = defaultVal || {} }
43 | transactionFn(val)
44 | store.set(key, val)
45 | }
46 | store.getAll = function() {}
47 |
48 | store.serialize = function(value) {
49 | return JSON.stringify(value)
50 | }
51 | store.deserialize = function(value) {
52 | if (typeof value != 'string') { return undefined }
53 | try { return JSON.parse(value) }
54 | catch(e) { return value || undefined }
55 | }
56 |
57 | // Functions to encapsulate questionable FireFox 3.6.13 behavior
58 | // when about.config::dom.storage.enabled === false
59 | // See https://github.com/marcuswestin/store.js/issues#issue/13
60 | function isLocalStorageNameSupported() {
61 | try { return (localStorageName in win && win[localStorageName]) }
62 | catch(err) { return false }
63 | }
64 |
65 | function isGlobalStorageNameSupported() {
66 | try { return (globalStorageName in win && win[globalStorageName] && win[globalStorageName][win.location.hostname]) }
67 | catch(err) { return false }
68 | }
69 |
70 | if (isLocalStorageNameSupported()) {
71 | storage = win[localStorageName]
72 | store.set = function(key, val) {
73 | if (val === undefined) { return store.remove(key) }
74 | storage.setItem(key, store.serialize(val))
75 | return val
76 | }
77 | store.get = function(key) { return store.deserialize(storage.getItem(key)) }
78 | store.remove = function(key) { storage.removeItem(key) }
79 | store.clear = function() { storage.clear() }
80 | store.getAll = function() {
81 | var ret = {}
82 | for (var i=0; idocument.w=window