Skip to content

Commit 9ca2fc1

Browse files
ianjenningsstephenlb
authored andcommitted
rltm.js (#5)
* working demo, except we still need to find a way to tell angular to update on message * whoops, remove scope apply * call scope apply in callback function, what we really need is promises * ok, actually needed rootscope.apply * remove commented out code * fix up example * highlight username * add rltm.js via bower, rework angular for new rltm lib * delete empty file stubs * bump version in package.json, edit license, remove bower_components * update rltm.js version * new support example, rewrite documentation, add support for private chats back * remove extra spacing and quhotes from examples * back to pubnub * document examples in readme.md
1 parent b669afd commit 9ca2fc1

37 files changed

Lines changed: 43316 additions & 265 deletions

angular-chat-config.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

angular-chat.js

Lines changed: 97 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,223 +1,137 @@
1-
// -- TODO --
2-
//
3-
// - https://developer.layer.com/docs/ios/integration
4-
// - AddressBook = Presence/State + ChannelGroups
5-
// - Notifications = History + PubSub
6-
// - Messages = History + PubSub
7-
// - Groups = History + PubSub
8-
// - TypeingIndicator = ???
9-
//
10-
// - Signals = PubSub
11-
// - History = History
12-
//
13-
// -- TODO --
14-
151
'use strict';
162

17-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
18-
// AngularJS Chat Module
19-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20-
angular.module( 'chat', [] );
3+
angular.module('chat', []);
214

22-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
235
// Common JS
24-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
256
if (typeof(exports) !== 'undefined') exports.chat = angular.module('chat');
267

27-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
28-
// >$ telnet nyancat.dakko.us
29-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30-
//
31-
// ▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄
32-
// █░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░█
33-
// █░▒▒▒▒▒▒▒▒▒▒▄▓▓▄▒▒▒▒░░▄▓▓▄
34-
// ▄▄▄ █░▒▒▒▒▒▒▒▒▒▒█▓▓▓▓▄▄▄▄▄▓▓▓▓
35-
// █▓▓█▄▄█░▒▒▒▒▒▒▒▒▒▒▄▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄
36-
// ▀▄▄▓▓█░▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▀ ▓▓▓▓▀ ▓▓▓▓
37-
// ▀▀█░▒▒▒▒▒▒▒▒▒▀▓▒▒▓▀▓▓▓▀▓▓▀▓▒▒█
38-
// ▄█░░▒▒▒▒▒▒▒▒▒▀▓▓▓▄▄▄▄▄▄▄▄▓▓▀
39-
// ▄▀▓▀█▄▄▄▄▄▄▄▄▄▄▄▄██████▀█▀▀
40-
// █▄▄▀ █▄▄▀ █▄▄▀ ▀▄▄█
41-
//
42-
43-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
44-
// Messages it's important to remember that you can
45-
// be deprived of your sanity listening to U2.
46-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8+
// define Angular Message module
479
angular.module('chat').service( 'Messages', [ 'ChatCore', function(ChatCore) {
48-
var Messages = this;
4910

50-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
11+
var self = this;
12+
5113
// Send Messages
52-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
53-
Messages.send = function(message) {
14+
self.send = function(message) {
15+
5416
if (!message.data) return;
5517

5618
ChatCore.publish({
57-
channel : message.to || 'global'
58-
, message : message.data
59-
, meta : ChatCore.user()
19+
to: message.to || 'global',
20+
message: message.data,
21+
user: ChatCore.user()
6022
});
23+
6124
};
6225

63-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6426
// Receive Messages
65-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66-
Messages.receive = function(fn) {
67-
function receiver(response) {
68-
response.data.m.forEach(function(msg){
69-
// Ignore messages without User Data
70-
// TODO
71-
if (!(msg.d && msg.u && msg.u.id)) return;
72-
fn({
73-
data : msg.d
74-
, id : msg.p.t
75-
, user : msg.u
76-
, self : msg.u.id == ChatCore.user().id
77-
});
78-
});
79-
}
80-
81-
Messages.subscription = ChatCore.subscribe({
82-
channels : [ 'global', ChatCore.user().id ].join(','),
83-
message : receiver
84-
});
27+
self.receive = function(fn) {
28+
self.subscription = ChatCore.subscribe(fn);
8529
};
8630

87-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88-
// Set/Get User and Save the World from that Bruce Willis movie.
89-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90-
Messages.user = function(data) {
91-
return ChatCore.user(data);
31+
// Set/Get User
32+
self.user = function(data) {
33+
return ChatCore.user(data);
9234
};
9335

94-
} ] );
36+
return self;
9537

96-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
97-
// AddressBook
98-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
99-
angular.module('chat').service( 'AddressBook', function() {
38+
}]);
10039

101-
} );
40+
// AngularJS Chat Core Service
41+
angular.module('chat').service('ChatCore',
42+
['$rootScope', '$http', 'config',
43+
function($rootScope, $http, config) {
10244

45+
var user = {
46+
id: uuid(),
47+
name: 'Anonymous'
48+
};
49+
50+
var self = this;
51+
52+
self.rltm = rltm(config.rltm);
53+
54+
// the global room everyone is in
55+
self.roomGlobal;
56+
57+
// my own private rooms
58+
self.roomPrivate;
59+
60+
// everyone elses private rooms
61+
self.rooms = {};
62+
63+
// Set User Data
64+
self.user = function(data) {
65+
66+
if (data) {
67+
angular.extend(user, data);
68+
}
10369

104-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
105-
// AngularJS Chat Core Service
106-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
107-
angular.module('chat').service( 'ChatCore', [ '$http', 'config', function(
108-
$http,
109-
config
110-
) {
111-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
112-
// API Keys
113-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114-
var pubkey = config.pubnub['publish-key']
115-
, subkey = config.pubnub['subscribe-key']
116-
, user = { id : uuid(), name : 'Nameless' };
117-
118-
var ChatCore = this;
119-
120-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121-
// Set User Data and we have to go Back to The Future.
122-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123-
ChatCore.user = function(data) {
124-
if (data) angular.extend( user, data );
12570
return user;
126-
};
12771

128-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129-
// Publish via PubNub
130-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131-
ChatCore.publish = function(setup) {
132-
var meta = setup.meta || ChatCore.user()
133-
, userid = ChatCore.user().id || 'nil';
134-
135-
var request = {
136-
method : 'GET'
137-
, params : { meta : meta, uuid : userid }
138-
, timeout : setup.timeout || 5000
139-
, success : function(){}
140-
, fail : function(){}
141-
};
142-
143-
//
144-
request.url = [
145-
'https://pubsub.pubnub.com'
146-
, '/publish/', pubkey
147-
, '/', subkey
148-
, '/0/', setup.channel
149-
, '/0/', encodeURIComponent(JSON.stringify(setup.message))
150-
].join('');
151-
152-
$http(request).then( request.success, request.fail );
15372
};
15473

155-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
156-
// Subscribe via PubNub
157-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158-
ChatCore.subscribe = function(setup) {
159-
var channels = setup.channels || 'a'
160-
, groups = setup.groups || ''
161-
, message = setup.message || function(){}
162-
, timeout = setup.timeout || 290000
163-
, timetoken = setup.timetoken || '0'
164-
, windowing = setup.windowing || 10
165-
, userid = ChatCore.user().id || 'nil'
166-
, userstate = ChatCore.user() || {}
167-
, stop = false
168-
, origin = 'ps'+(Math.random()+'').split('.')[1]+'.pubnub.com';
169-
170-
// Request Object
171-
var request = {
172-
method : 'GET'
173-
, url : ''
174-
, params : { uuid : userid, state : userstate }
175-
, timeout : timeout
176-
, success : next
177-
, fail : function(){ timetoken = '0'; next() }
178-
};
179-
180-
// Channel Groups
181-
if (groups) request.params['channel-group'] = groups;
182-
183-
// Subscribe Loop
184-
function next(response) {
185-
if (stop) return;
186-
if (response) {
187-
timetoken = timetoken == '0' ? 1000 : response.data.t.t;
188-
message(response);
74+
// Publish over network
75+
self.publish = function(setup) {
76+
77+
var user = setup.user || self.user();
78+
79+
var data = setup.data;
80+
81+
if(setup.to) {
82+
83+
if(!self.rooms[setup.to]) {
84+
self.rooms[setup.to] = self.rltm.join(setup.to);
18985
}
19086

191-
request.url = [
192-
'https://', origin
193-
, '/v2/subscribe/', subkey
194-
, '/', channels
195-
, '/0/', timetoken
196-
].join('');
87+
return self.rooms[setup.to].publish({
88+
data: setup.message,
89+
user: user
90+
});
19791

198-
setTimeout( function() {
199-
$http(request).then( request.success, request.fail );
200-
}, windowing );
201-
}
92+
} else {
93+
94+
return self.roomGlobal.publish({
95+
data: setup.message,
96+
user: user
97+
});
20298

203-
// Cancel Subscription
204-
function unsubscribe() {
205-
stop = true;
20699
}
207100

208-
// Start Subscribe Loop
209-
next();
101+
};
102+
103+
// Subscribe to new messages
104+
self.subscribe = function(fn) {
105+
106+
console.log('i am ', self.user().id)
107+
108+
self.roomGlobal = self.rltm.join('global');
109+
self.roomPrivate = self.rltm.join(self.user().id);
110+
111+
self.roomGlobal.on('message', function(uuid, data) {
112+
113+
console.log('public messages', data)
114+
115+
fn(data, false);
116+
$rootScope.$apply();
117+
});
118+
119+
self.roomPrivate.on('message', function(uuid, data) {
120+
121+
console.log('private messages', data)
122+
123+
fn(data, true);
124+
$rootScope.$apply();
125+
126+
});
127+
128+
return self.room;
210129

211-
// Allow Cancelling Subscriptions
212-
return {
213-
unsubscribe : unsubscribe
214-
};
215130
};
216-
} ] );
217131

218-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
219-
// UUID
220-
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
132+
}]);
133+
134+
// UUID utility
221135
function uuid() {
222136
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
223137
function(c) {

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"angular"
1717
],
1818
"dependencies": {
19-
"angular": ">= 1.4.8"
19+
"angular": ">= 1.4.8",
20+
"rltm": "^1.0.3"
2021
},
2122
"repository": {
2223
"type": "git",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "angular",
3+
"version": "1.6.0",
4+
"license": "MIT",
5+
"main": "./angular.js",
6+
"ignore": [],
7+
"dependencies": {},
8+
"homepage": "https://github.com/angular/bower-angular",
9+
"_release": "1.6.0",
10+
"_resolution": {
11+
"type": "version",
12+
"tag": "v1.6.0",
13+
"commit": "2c9a5a213e66013a0930230448a4de0f471ff1f6"
14+
},
15+
"_source": "https://github.com/angular/bower-angular.git",
16+
"_target": ">= 1.4.8",
17+
"_originalSource": "angular"
18+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Angular
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.

0 commit comments

Comments
 (0)