root/tags/2C10/JVBuddy.m

Revision 1823, 23.2 kB (checked in by timothy, 4 years ago)

Moved Colloquy to a pre-compiled header. Removed all #imports that are part of the Cocoa, WebKit? and AGRegex frameworks. Removed all @class declarations that are part of the Cocoa frameworks.

Line 
1 #import <AddressBook/AddressBook.h>
2 #import <ChatCore/MVChatConnection.h>
3 #import <ChatCore/NSStringAdditions.h>
4
5 #import "JVBuddy.h"
6 #import "MVConnectionsController.h"
7
8 NSString *JVBuddyCameOnlineNotification = @"JVBuddyCameOnlineNotification";
9 NSString *JVBuddyWentOfflineNotification = @"JVBuddyWentOfflineNotification";
10
11 NSString *JVBuddyNicknameCameOnlineNotification = @"JVBuddyNicknameCameOnlineNotification";
12 NSString *JVBuddyNicknameWentOfflineNotification = @"JVBuddyNicknameWentOfflineNotification";
13 NSString *JVBuddyNicknameStatusChangedNotification = @"JVBuddyNicknameStatusChangedNotification";
14
15 NSString *JVBuddyActiveNicknameChangedNotification = @"JVBuddyActiveNicknameChangedNotification";
16
17 static JVBuddyName _mainPreferredName = JVBuddyFullName;
18
19 @implementation JVBuddy
20 + (JVBuddyName) preferredName {
21         extern JVBuddyName _mainPreferredName;
22         return _mainPreferredName;
23 }
24
25 + (void) setPreferredName:(JVBuddyName) preferred {
26         extern JVBuddyName _mainPreferredName;
27         _mainPreferredName = preferred;
28 }
29
30 + (id) buddyWithPerson:(ABPerson *) person {
31         return [[[[self class] alloc] initWithPerson:person] autorelease];
32 }
33
34 + (id) buddyWithUniqueIdentifier:(NSString *) identifier {
35         ABRecord *person = [[ABAddressBook sharedAddressBook] recordForUniqueId:identifier];
36         if( [person isKindOfClass:[ABPerson class]] )
37                 return [[[[self class] alloc] initWithPerson:(ABPerson *)person] autorelease];
38         return nil;
39 }
40
41 #pragma mark -
42
43 - (id) initWithPerson:(ABPerson *) person {
44         if( ( self = [super init] ) ) {
45                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _registerWithConnection: ) name:MVChatConnectionDidConnectNotification object:nil];
46                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _disconnected: ) name:MVChatConnectionDidDisconnectNotification object:nil];
47                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _nicknameChange: ) name:MVChatConnectionUserNicknameChangedNotification object:nil];
48                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOnline: ) name:MVChatConnectionBuddyIsOnlineNotification object:nil];
49                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOffline: ) name:MVChatConnectionBuddyIsOfflineNotification object:nil];
50                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyAwayStatusChange: ) name:MVChatConnectionBuddyIsAwayNotification object:nil];
51                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyAwayStatusChange: ) name:MVChatConnectionBuddyIsUnawayNotification object:nil];
52                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyIdleUpdate: ) name:MVChatConnectionBuddyIsIdleNotification object:nil];
53                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyIdleUpdate: ) name:MVChatConnectionGotUserIdleNotification object:nil];
54
55                 _person = [person retain];
56                 _nicknames = [[NSMutableSet set] retain];
57                 _onlineNicknames = [[NSMutableSet set] retain];
58                 _nicknameStatus = [[NSMutableDictionary dictionary] retain];
59                 _activeNickname = nil;
60
61                 ABMultiValue *value = [person valueForProperty:@"IRCNickname"];
62                 unsigned int i = 0, count = [value count];
63                 NSURL *url = nil;
64                 for( i = 0; i < count; i++ ) {
65                         url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [[value valueAtIndex:i] stringByEncodingIllegalURLCharacters], [[value labelAtIndex:i] stringByEncodingIllegalURLCharacters]]];
66                         [_nicknames addObject:url];
67                         [_nicknameStatus setObject:[NSMutableDictionary dictionary] forKey:url];
68                         [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyOfflineStatus] forKey:@"status"];
69                         if( ! [self activeNickname] ) [self setActiveNickname:url];
70                 }
71
72                 [self registerWithApplicableConnections];
73         }
74         return self;
75 }
76
77 - (void) dealloc {
78         [self unregisterWithApplicableConnections];
79
80         [[NSNotificationCenter defaultCenter] removeObserver:self];
81
82         [_person release];
83         [_nicknames release];
84         [_onlineNicknames release];
85         [_nicknameStatus release];
86         [_activeNickname release];
87
88         _person = nil;
89         _nicknames = nil;
90         _onlineNicknames = nil;
91         _nicknameStatus = nil;
92         _activeNickname = nil;
93
94         [super dealloc];
95 }
96
97 #pragma mark -
98
99 - (void) registerWithApplicableConnections {
100         NSEnumerator *enumerator = [_nicknames objectEnumerator];
101         NSEnumerator *connectionEnumerator = nil;
102         MVChatConnection *connection = nil;
103         NSURL *nick = nil;
104         while( ( nick = [enumerator nextObject] ) ) {
105                 connectionEnumerator = [[[MVConnectionsController defaultManager] connectionsForServerAddress:[nick host]] objectEnumerator];
106                 while( ( connection = [connectionEnumerator nextObject] ) )
107                         [connection addUserToNotificationList:[nick user]];
108         }
109 }
110
111 - (void) unregisterWithApplicableConnections {
112         NSEnumerator *enumerator = [_nicknames objectEnumerator];
113         NSEnumerator *connectionEnumerator = nil;
114         MVChatConnection *connection = nil;
115         NSURL *nick = nil;
116         while( ( nick = [enumerator nextObject] ) ) {
117                 connectionEnumerator = [[[MVConnectionsController defaultManager] connectionsForServerAddress:[nick host]] objectEnumerator];
118                 while( ( connection = [connectionEnumerator nextObject] ) )
119                         [connection removeUserFromNotificationList:[nick user]];
120         }
121 }
122
123 #pragma mark -
124
125 - (NSURL *) activeNickname {
126         return [[_activeNickname retain] autorelease];
127 }
128
129 - (void) setActiveNickname:(NSURL *) nickname {
130         [_activeNickname autorelease];
131         _activeNickname = [nickname retain];
132 }
133
134 #pragma mark -
135
136 - (JVBuddyStatus) status {
137         if( [self activeNickname] )
138                 return (JVBuddyStatus)[[[_nicknameStatus objectForKey:[self activeNickname]] objectForKey:@"status"] unsignedIntValue];
139         return JVBuddyOfflineStatus;
140 }
141
142 - (BOOL) isOnline {
143         return (BOOL)( [self status] != JVBuddyOfflineStatus );
144 }
145
146 - (NSTimeInterval) idleTime {
147         if( [self activeNickname] )
148                 return (NSTimeInterval)[[[_nicknameStatus objectForKey:[self activeNickname]] objectForKey:@"idle"] doubleValue];
149         return 0.;
150 }
151
152 - (NSString *) awayMessage {
153         if( [self activeNickname] )
154                 return [[_nicknameStatus objectForKey:[self activeNickname]] objectForKey:@"awayMessage"];
155         return nil;
156 }
157
158 #pragma mark -
159
160 - (NSSet *) nicknames {
161         return [[_nicknames retain] autorelease];
162 }
163
164 - (NSSet *) onlineNicknames {
165         return [[_onlineNicknames retain] autorelease];
166 }
167
168 #pragma mark -
169
170 - (void) addNickname:(NSURL *) nickname {
171         if( [_nicknames containsObject:nickname] ) return;
172
173         ABMutableMultiValue *value = [[[_person valueForProperty:@"IRCNickname"] mutableCopy] autorelease];
174         [value addValue:[nickname user] withLabel:[nickname host]];
175         [_person setValue:value forProperty:@"IRCNickname"];
176
177         if( ! [_nicknames count] || ! [self activeNickname] )
178                 [self setActiveNickname:nickname];
179
180         [_nicknames addObject:nickname];
181
182         [[ABAddressBook sharedAddressBook] save];
183
184         [self registerWithApplicableConnections];
185 }
186
187 - (void) removeNickname:(NSURL *) nickname {
188         if( ! [_nicknames containsObject:nickname] ) return;
189
190         ABMutableMultiValue *value = [[[_person valueForProperty:@"IRCNickname"] mutableCopy] autorelease];
191         int i = 0, count = [value count];
192
193         for( i = count - 1; i >= 0; i-- )
194                 if( [[nickname user] caseInsensitiveCompare:[value valueAtIndex:i]] == NSOrderedSame && [[nickname host] caseInsensitiveCompare:[value labelAtIndex:i]] == NSOrderedSame )
195                         [value removeValueAndLabelAtIndex:i];
196
197         [_nicknames removeObject:nickname];
198         [_onlineNicknames removeObject:nickname];
199         [_person setValue:value forProperty:@"IRCNickname"];
200
201         if( [[self activeNickname] isEqual:nickname] )
202                 [self setActiveNickname:( [_onlineNicknames count] ? [_onlineNicknames anyObject] : [_nicknames anyObject] )];
203
204         [[ABAddressBook sharedAddressBook] save];
205 }
206
207 - (void) replaceNickname:(NSURL *) old withNickname:(NSURL *) new {
208         [self removeNickname:old];
209         [self addNickname:new];
210 }
211
212 #pragma mark -
213
214 - (NSImage *) picture {
215         return [[[NSImage alloc] initWithData:[_person imageData]] autorelease];
216 }
217
218 - (void) setPicture:(NSImage *) picture {
219         [_person setImageData:[picture TIFFRepresentation]];
220 }
221
222 #pragma mark -
223
224 - (NSString *) preferredName {
225         switch( [[self class] preferredName] ) {
226                 default:
227                 case JVBuddyFullName:
228                         return [self compositeName];
229                 case JVBuddyGivenNickname:
230                         if( [[self givenNickname] length] )
231                                 return [self givenNickname];
232                 case JVBuddyActiveNickname:
233                         return [[self activeNickname] user];
234         }
235         return [[self activeNickname] user];
236 }
237
238 - (JVBuddyName) preferredNameWillReturn {
239         NSString *firstName = [self firstName];
240         NSString *lastName = [self lastName];
241
242         if( [firstName length] || [lastName length] ) return JVBuddyFullName;
243         if( [[self givenNickname] length] ) return JVBuddyGivenNickname;
244
245         return JVBuddyActiveNickname;
246 }
247
248 - (unsigned int) availableNames {
249         unsigned int ret = JVBuddyActiveNickname;
250         NSString *firstName = [self firstName];
251         NSString *lastName = [self lastName];
252
253         if( [firstName length] || [lastName length] ) ret |= JVBuddyFullName;
254         if( [[self givenNickname] length] ) ret |= JVBuddyGivenNickname;
255
256         return ret;
257 }
258
259 - (NSString *) compositeName {
260         NSString *firstName = [self firstName];
261         NSString *lastName = [self lastName];
262
263         if( ! firstName && lastName ) return lastName;
264         else if( firstName && ! lastName ) return firstName;
265         else if( firstName && lastName ) {
266                 return [NSString stringWithFormat:@"%@ %@", firstName, lastName];
267         }
268
269         firstName = [self givenNickname];
270         if( [firstName length] ) return firstName;
271
272         return [[self activeNickname] user];
273 }
274
275 - (NSString *) firstName {
276         return [_person valueForProperty:kABFirstNameProperty];
277 }
278
279 - (NSString *) lastName {
280         return [_person valueForProperty:kABLastNameProperty];
281 }
282
283 - (NSString *) primaryEmail {
284         ABMultiValue *value = [_person valueForProperty:kABEmailProperty];
285         return [value valueAtIndex:[value indexForIdentifier:[value primaryIdentifier]]];
286 }
287
288 - (NSString *) givenNickname {
289         return [_person valueForProperty:kABNicknameProperty];
290 }
291
292 #pragma mark -
293
294 - (void) setFirstName:(NSString *) name {
295         [_person setValue:name forProperty:kABFirstNameProperty];
296         [[ABAddressBook sharedAddressBook] save];
297 }
298
299 - (void) setLastName:(NSString *) name {
300         [_person setValue:name forProperty:kABLastNameProperty];
301         [[ABAddressBook sharedAddressBook] save];
302 }
303
304 - (void) setPrimaryEmail:(NSString *) email {
305         ABMutableMultiValue *value = [[[_person valueForProperty:kABEmailProperty] mutableCopy] autorelease];
306
307         if( ! value ) {
308                 value = [[[ABMutableMultiValue alloc] init] autorelease];
309                 [value addValue:email withLabel:kABOtherLabel];
310         } else [value replaceValueAtIndex:[value indexForIdentifier:[value primaryIdentifier]] withValue:email];
311
312         [_person setValue:value forProperty:kABEmailProperty];
313         [[ABAddressBook sharedAddressBook] save];
314 }
315
316 - (void) setGivenNickname:(NSString *) name {
317         [_person setValue:name forProperty:kABNicknameProperty];
318         [[ABAddressBook sharedAddressBook] save];
319 }
320
321 #pragma mark -
322
323 - (NSString *) uniqueIdentifier {
324         return [_person uniqueId];
325 }
326
327 - (ABPerson *) person {
328         return [[_person retain] autorelease];
329 }
330
331 - (void) editInAddressBook {
332         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"addressbook://%@?edit", [_person uniqueId]]];
333         [[NSWorkspace sharedWorkspace] openURL:url];
334 }
335
336 - (void) viewInAddressBook {
337         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"addressbook://%@", [_person uniqueId]]];
338         [[NSWorkspace sharedWorkspace] openURL:url];
339 }
340
341 #pragma mark -
342 #pragma mark Comparisons
343
344 - (NSComparisonResult) availabilityCompare:(JVBuddy *) buddy {
345         unsigned int b1 = 0, b2 = 0;
346
347         if( [self status] == JVBuddyAwayStatus ) b1 = 2;
348         else if( [self status] == JVBuddyIdleStatus ) b1 = 1;
349         else if( [self status] == JVBuddyAvailableStatus ) b1 = 0;
350         else b1 = 3;
351
352         if( [buddy status] == JVBuddyAwayStatus ) b2 = 2;
353         else if( [buddy status] == JVBuddyIdleStatus ) b2 = 1;
354         else if( [buddy status] == JVBuddyAvailableStatus ) b2 = 0;
355         else b2 = 3;
356
357         if( b1 > b2 ) return NSOrderedDescending;
358         else if( b1 < b2 ) return NSOrderedAscending;
359         return [self lastNameCompare:buddy];
360 }
361
362 - (NSComparisonResult) firstNameCompare:(JVBuddy *) buddy {
363         NSComparisonResult ret = NSOrderedSame;
364         NSString *name1 = [self firstName];
365         NSString *name2 = [buddy firstName];
366
367         if( ! [name1 length] ) name1 = [self lastName];
368         if( ! [name2 length] ) name2 = [buddy lastName];
369
370         if( ! [name1 length] && [name2 length] ) return NSOrderedAscending;
371         else if( ! [name2 length] && [name1 length]  ) return NSOrderedDescending;
372
373         ret = [name1 localizedCaseInsensitiveCompare:name2];
374         if( ret != NSOrderedSame ) return ret;
375
376         name1 = [self lastName];
377         name2 = [buddy lastName];
378
379         if( ! [name1 length] && [name2 length] ) return NSOrderedAscending;
380         else if( ! [name2 length] && [name1 length]  ) return NSOrderedDescending;
381
382         return [name1 localizedCaseInsensitiveCompare:name2];
383 }
384
385 - (NSComparisonResult) lastNameCompare:(JVBuddy *) buddy {
386         NSComparisonResult ret = NSOrderedSame;
387         NSString *name1 = [self lastName];
388         NSString *name2 = [buddy lastName];
389
390         if( ! [name1 length] ) name1 = [self firstName];
391         if( ! [name2 length] ) name2 = [buddy firstName];
392
393         if( ! [name1 length] && [name2 length] ) return NSOrderedAscending;
394         else if( ! [name2 length] && [name1 length]  ) return NSOrderedDescending;
395
396         ret = [name1 localizedCaseInsensitiveCompare:name2];
397         if( ret != NSOrderedSame ) return ret;
398
399         name1 = [self firstName];
400         name2 = [buddy firstName];
401
402         if( ! [name1 length] && [name2 length] ) return NSOrderedAscending;
403         else if( ! [name2 length] && [name1 length]  ) return NSOrderedDescending;
404
405         return [name1 localizedCaseInsensitiveCompare:name2];
406 }
407
408 - (NSComparisonResult) serverCompare:(JVBuddy *) buddy {
409         NSString *name1 = [[self activeNickname] host];
410         NSString *name2 = [[buddy activeNickname] host];
411         NSComparisonResult ret = [name1 caseInsensitiveCompare:name2];
412         return ( ret != NSOrderedSame ? ret : [self availabilityCompare:buddy] );
413 }
414
415 - (NSComparisonResult) nicknameCompare:(JVBuddy *) buddy {
416         NSString *name1 = [[self activeNickname] user];
417         NSString *name2 = [[buddy activeNickname] user];
418         return [name1 caseInsensitiveCompare:name2];
419 }
420 @end
421
422 #pragma mark -
423
424 @implementation JVBuddy (JVBuddyPrivate)
425 - (void) _buddyOnline:(NSNotification *) notification {
426         MVChatConnection *connection = [notification object];
427         NSString *who = [[notification userInfo] objectForKey:@"who"];
428         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [who stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
429         if( [_nicknames containsObject:url] ) {
430                 BOOL cameOnline = ( ! [_onlineNicknames count] ? YES : NO );
431                 [_onlineNicknames addObject:url];
432                 [_nicknameStatus setObject:[NSMutableDictionary dictionary] forKey:url];
433                 [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyAvailableStatus] forKey:@"status"];
434                 if( [self status] == JVBuddyOfflineStatus ) [self setActiveNickname:url];
435                 if( cameOnline ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyCameOnlineNotification object:self userInfo:nil];
436                 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyNicknameCameOnlineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:url, @"nickname", nil]];
437         }
438 }
439
440 - (void) _buddyOffline:(NSNotification *) notification {
441         MVChatConnection *connection = [notification object];
442         NSString *who = [[notification userInfo] objectForKey:@"who"];
443         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [who stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
444         if( [_onlineNicknames containsObject:url] ) {
445                 [_onlineNicknames removeObject:url];
446                 [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyOfflineStatus] forKey:@"status"];
447                 if( [_onlineNicknames count] ) [self setActiveNickname:[_onlineNicknames anyObject]];
448                 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyNicknameWentOfflineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:url, @"nickname", nil]];
449                 if( ! [_onlineNicknames count] ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyWentOfflineNotification object:self userInfo:nil];
450         }
451 }
452
453 - (void) _buddyIdleUpdate:(NSNotification *) notification {
454         MVChatConnection *connection = [notification object];
455         NSString *who = [[notification userInfo] objectForKey:@"who"];
456         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [who stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
457         if( [_onlineNicknames containsObject:url] ) {
458                 NSNumber *idle = [[notification userInfo] objectForKey:@"idle"];
459                 [[_nicknameStatus objectForKey:url] setObject:idle forKey:@"idle"];
460                 if( [idle doubleValue] >= 600. && (JVBuddyStatus)[[[_nicknameStatus objectForKey:url] objectForKey:@"status"] unsignedIntValue] != JVBuddyAwayStatus ) {
461                         [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyIdleStatus] forKey:@"status"];
462                 } else if( [idle doubleValue] < 600. && (JVBuddyStatus)[[[_nicknameStatus objectForKey:url] objectForKey:@"status"] unsignedIntValue] == JVBuddyIdleStatus ) {
463                         [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyAvailableStatus] forKey:@"status"];
464                 }
465
466                 NSNotification *notification = [NSNotification notificationWithName:JVBuddyNicknameStatusChangedNotification object:self];
467                 [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP coalesceMask:( NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender ) forModes:nil];
468         }
469 }
470
471 - (void) _buddyAwayStatusChange:(NSNotification *) notification {
472         MVChatConnection *connection = [notification object];
473         NSString *who = [[notification userInfo] objectForKey:@"who"];
474         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [who stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
475         if( [_onlineNicknames containsObject:url] ) {
476                 BOOL away = ( [[notification name] isEqualToString:MVChatConnectionBuddyIsAwayNotification] ? YES : NO );
477                 [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithBool:away] forKey:@"away"];
478                 if( away ) {
479                         [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyAwayStatus] forKey:@"status"];
480                         if( [[notification userInfo] objectForKey:@"msg"] )
481                                 [[_nicknameStatus objectForKey:url] setObject:[[[[notification userInfo] objectForKey:@"msg"] copy] autorelease] forKey:@"awayMessage"];
482                 } else {
483                         NSTimeInterval idle = [[[_nicknameStatus objectForKey:url] objectForKey:@"idle"] doubleValue];
484                         if( idle >= 600. ) [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyIdleStatus] forKey:@"status"];
485                         else [[_nicknameStatus objectForKey:url] setObject:[NSNumber numberWithUnsignedInt:JVBuddyAvailableStatus] forKey:@"status"];
486                         [[_nicknameStatus objectForKey:url] removeObjectForKey:@"awayMessage"];
487                 }
488
489                 NSNotification *notification = [NSNotification notificationWithName:JVBuddyNicknameStatusChangedNotification object:self];
490                 [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP coalesceMask:( NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender ) forModes:nil];
491         }
492 }
493
494 - (void) _registerWithConnection:(NSNotification *) notification {
495         MVChatConnection *connection = [notification object];
496         NSEnumerator *enumerator = [_nicknames objectEnumerator];
497         NSURL *nick = nil;
498
499         while( ( nick = [enumerator nextObject] ) )
500                 if( [[nick host] caseInsensitiveCompare:[connection server]] == NSOrderedSame )
501                         [connection addUserToNotificationList:[nick user]];
502 }
503
504 - (void) _disconnected:(NSNotification *) notification {
505         NSEnumerator *enumerator = [[[MVConnectionsController defaultManager] connections] objectEnumerator];
506         MVChatConnection *connection = nil;
507         unsigned int count = 0;
508
509         while( ( connection = [enumerator nextObject] ) )
510                 if( [[connection server] caseInsensitiveCompare:[connection server]] == NSOrderedSame && [connection isConnected] )
511                         count++;
512
513         if( count >= 1 ) return;
514
515         connection = [notification object];
516         enumerator = [[[_onlineNicknames copy] autorelease] objectEnumerator];
517         NSURL *nick = nil;
518         while( ( nick = [enumerator nextObject] ) ) {
519                 if( [[nick host] caseInsensitiveCompare:[connection server]] == NSOrderedSame ) {
520                         [_onlineNicknames removeObject:nick];
521                         [[_nicknameStatus objectForKey:nick] setObject:[NSNumber numberWithUnsignedInt:JVBuddyOfflineStatus] forKey:@"status"];
522                         [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyNicknameWentOfflineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:nick, @"nickname", nil]];
523                         if( ! [_onlineNicknames count] ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyWentOfflineNotification object:self userInfo:nil];
524                 }
525         }
526 }
527
528 - (void) _nicknameChange:(NSNotification *) notification {
529         MVChatConnection *connection = [notification object];
530         NSString *who = [[notification userInfo] objectForKey:@"oldNickname"];
531         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [who stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
532
533         if( [_onlineNicknames containsObject:url] ) {
534                 NSString *new = [[notification userInfo] objectForKey:@"newNickname"];
535                 NSURL *urlNew = [NSURL URLWithString:[NSString stringWithFormat:@"irc://%@@%@", [new stringByEncodingIllegalURLCharacters], [[connection server] stringByEncodingIllegalURLCharacters]]];
536
537                 [_nicknames removeObject:url];
538                 [_nicknames addObject:urlNew];
539
540                 [_onlineNicknames removeObject:url];
541                 [_onlineNicknames addObject:urlNew];
542
543                 NSMutableDictionary *info = [[[_nicknameStatus objectForKey:url] retain] autorelease];
544                 [_nicknameStatus removeObjectForKey:url];
545                 [_nicknameStatus setObject:info forKey:urlNew];
546
547                 if( [[self activeNickname] isEqual:url] ) [self setActiveNickname:urlNew];
548         }
549 }
550 @end
551
552 #pragma mark -
553
554 @implementation JVBuddy (JVBuddyScripting)
555 - (NSDictionary *) activeNicknameDictionary {
556         MVChatConnection *connection = [[MVConnectionsController defaultManager] connectionForServerAddress:[[self activeNickname] host]];
557         return [NSDictionary dictionaryWithObjectsAndKeys:connection, @"connection", [[self activeNickname] user], @"nickname", nil];
558 }
559
560 - (NSArray *) nicknamesArray {
561         NSMutableArray *ret = [NSMutableArray arrayWithCapacity:[_nicknames count]];
562         NSEnumerator *enumerator = [_nicknames objectEnumerator];
563         NSURL *nick = nil;
564
565         while( ( nick = [enumerator nextObject] ) ) {
566                 MVChatConnection *connection = [[MVConnectionsController defaultManager] connectionForServerAddress:[nick host]];
567                 if( ! connection ) continue;
568                 NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:connection, @"connection", [nick user], @"nickname", nil];
569                 [ret addObject:info];
570         }
571
572         return ret;
573 }
574
575 - (NSArray *) onlineNicknamesArray {
576         NSMutableArray *ret = [NSMutableArray arrayWithCapacity:[_nicknames count]];
577         NSEnumerator *enumerator = [_onlineNicknames objectEnumerator];
578         NSURL *nick = nil;
579
580         while( ( nick = [enumerator nextObject] ) ) {
581                 MVChatConnection *connection = [[MVConnectionsController defaultManager] connectionForServerAddress:[nick host]];
582                 if( ! connection ) continue;
583                 NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:connection, @"connection", [nick user], @"nickname", nil];
584                 [ret addObject:info];
585         }
586
587         return ret;
588 }
589
590 - (void) editInAddressBookScriptCommand:(NSScriptCommand *) command {
591         [self editInAddressBook];
592 }
593
594 - (void) viewInAddressBookScriptCommand:(NSScriptCommand *) command {
595         [self viewInAddressBook];
596 }
597 @end
Note: See TracBrowser for help on using the browser.