Changeset 3190
- Timestamp:
- 04/02/06 05:32:29 (2 years ago)
- Files:
-
- trunk/Chat Core.exp (modified) (2 diffs)
- trunk/Chat Core.xcodeproj/project.pbxproj (modified) (1 diff)
- trunk/Chat Core/MVChatConnection.h (modified) (1 diff)
- trunk/Chat Core/MVChatConnection.m (modified) (1 diff)
- trunk/Chat Core/MVChatUser.h (modified) (1 diff)
- trunk/Chat Core/MVChatUser.m (modified) (1 diff)
- trunk/Chat Core/MVChatUserWatchRule.h (modified) (2 diffs)
- trunk/Chat Core/MVChatUserWatchRule.m (modified) (5 diffs)
- trunk/Chat Core/MVIRCChatConnection.m (modified) (2 diffs)
- trunk/Colloquy.xcodeproj/project.pbxproj (modified) (2 diffs)
- trunk/Controllers/MVBuddyListController.m (modified) (3 diffs)
- trunk/Controllers/MVConnectionsController.m (modified) (2 diffs)
- trunk/Models/JVBuddy.h (modified) (4 diffs)
- trunk/Models/JVBuddy.m (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Chat Core.exp
r3175 r3190 2 2 .objc_class_name_MVChatRoom 3 3 .objc_class_name_MVChatUser 4 .objc_class_name_MVChatUserWatchRule 4 5 .objc_class_name_MVFileTransfer 5 6 .objc_class_name_MVDownloadFileTransfer … … 67 68 _MVChatUserInformationUpdatedNotification 68 69 _MVChatUserAttributeUpdatedNotification 70 _MVChatUserWatchRuleMatchedNotification 69 71 _MVDownloadFileTransferOfferNotification 70 72 _MVFileTransferStartedNotification trunk/Chat Core.xcodeproj/project.pbxproj
r3179 r3190 31 31 1C7C776907DBBA4500FB5F83 /* NSScriptCommandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C7C776707DBBA4500FB5F83 /* NSScriptCommandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 32 1C7C776A07DBBA4500FB5F83 /* NSScriptCommandAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C7C776807DBBA4500FB5F83 /* NSScriptCommandAdditions.m */; }; 33 1C8AAEFE09D69F2700CF29EB /* MVChatUserWatchRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C8AAEFC09D69F2700CF29EB /* MVChatUserWatchRule.h */; };33 1C8AAEFE09D69F2700CF29EB /* MVChatUserWatchRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C8AAEFC09D69F2700CF29EB /* MVChatUserWatchRule.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34 34 1C8AAEFF09D69F2700CF29EB /* MVChatUserWatchRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C8AAEFD09D69F2700CF29EB /* MVChatUserWatchRule.m */; }; 35 35 1C8AAF2B09D6A0A100CF29EB /* AGRegex.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C8AAF2609D6A0A100CF29EB /* AGRegex.framework */; }; trunk/Chat Core/MVChatConnection.h
r3186 r3190 252 252 #pragma mark - 253 253 254 - (void) startWatchingUser:(MVChatUser *) user;255 - (void) stopWatchingUser:(MVChatUser *) user;256 257 #pragma mark -258 259 254 - (void) addChatUserWatchRule:(MVChatUserWatchRule *) rule; 260 255 - (void) removeChatUserWatchRule:(MVChatUserWatchRule *) rule; trunk/Chat Core/MVChatConnection.m
r3186 r3190 666 666 #pragma mark - 667 667 668 - (void) startWatchingUser:(MVChatUser *) user {669 // subclass this method, if needed670 }671 672 - (void) stopWatchingUser:(MVChatUser *) user {673 // subclass this method, if needed674 }675 676 668 - (void) addChatUserWatchRule:(MVChatUserWatchRule *) rule { 669 NSParameterAssert( rule != nil ); 677 670 if( ! _chatUserWatchRules ) 678 671 _chatUserWatchRules = [[NSMutableSet allocWithZone:nil] initWithCapacity:10]; 679 672 @synchronized( _chatUserWatchRules ) { 680 [_chatUserWatchRules addObject:rule]; 673 if( ! [_chatUserWatchRules containsObject:rule] ) 674 [_chatUserWatchRules addObject:rule]; 681 675 } 682 676 } 683 677 684 678 - (void) removeChatUserWatchRule:(MVChatUserWatchRule *) rule { 679 NSParameterAssert( rule != nil ); 685 680 @synchronized( _chatUserWatchRules ) { 686 681 [_chatUserWatchRules removeObject:rule]; trunk/Chat Core/MVChatUser.h
r3186 r3190 125 125 - (unsigned long) modes; 126 126 127 - (void) startWatching;128 - (void) stopWatching;129 130 127 - (void) refreshInformation; 131 128 trunk/Chat Core/MVChatUser.m
r3186 r3190 363 363 #pragma mark - 364 364 365 - (void) startWatching {366 [[self connection] startWatchingUser:self];367 }368 369 - (void) stopWatching {370 [[self connection] stopWatchingUser:self];371 }372 373 #pragma mark -374 375 365 - (void) refreshInformation { 376 366 // subclass this method, if needed trunk/Chat Core/MVChatUserWatchRule.h
r3187 r3190 15 15 AGRegex *_addressRegex; 16 16 NSData *_publicKey; 17 NSArray *_applicableServerDomains; 17 18 BOOL _interim; 18 19 } … … 47 48 - (BOOL) isInterim; 48 49 - (void) setInterim:(BOOL) interim; 50 51 - (NSArray *) applicableServerDomains; 52 - (void) setApplicableServerDomains:(NSArray *) serverDomains; 49 53 @end trunk/Chat Core/MVChatUserWatchRule.m
r3187 r3190 17 17 [self setPublicKey:[dictionary objectForKey:@"publicKey"]]; 18 18 [self setInterim:[[dictionary objectForKey:@"interim"] boolValue]]; 19 [self setApplicableServerDomains:[dictionary objectForKey:@"applicableServerDomains"]]; 19 20 } 20 21 … … 30 31 [self setPublicKey:[self publicKey]]; 31 32 [self setInterim:[self isInterim]]; 33 [self setApplicableServerDomains:[self applicableServerDomains]]; 32 34 return copy; 33 35 } … … 41 43 if( _publicKey ) [dictionary setObject:_nickname forKey:@"publicKey"]; 42 44 if( _interim ) [dictionary setObject:[NSNumber numberWithBool:_interim] forKey:@"interim"]; 45 if( _applicableServerDomains ) [dictionary setObject:_applicableServerDomains forKey:@"applicableServerDomains"]; 43 46 return [dictionary autorelease]; 44 47 } … … 81 84 82 85 NSString *string = [user nickname]; 83 if( _nicknameRegex && string && ! [_nicknameRegex findInString:string] ) return NO; 84 if( ! _nicknameRegex && _nickname && string && [_nickname length] && ! [_nickname isEqualToString:string] ) return NO; 86 if( _nicknameRegex && ! string ) return NO; 87 if( _nicknameRegex && ! [_nicknameRegex findInString:string] ) return NO; 88 if( ! _nicknameRegex && _nickname && [_nickname length] && ! [_nickname isEqualToString:string] ) return NO; 85 89 86 90 string = [user username]; 87 if( _usernameRegex && string && ! [_usernameRegex findInString:string] ) return NO; 88 if( ! _usernameRegex && _username && string && [_username length] && ! [_username isEqualToString:string] ) return NO; 91 if( _usernameRegex && ! string ) return NO; 92 if( _usernameRegex && ! [_usernameRegex findInString:string] ) return NO; 93 if( ! _usernameRegex && _username && [_username length] && ! [_username isEqualToString:string] ) return NO; 89 94 90 95 string = [user address]; 91 if( _addressRegex && string && ! [_addressRegex findInString:string] ) return NO; 92 if( ! _addressRegex && _address && string && [_address length] && ! [_address isEqualToString:string] ) return NO; 96 if( _addressRegex && ! string ) return NO; 97 if( _addressRegex && ! [_addressRegex findInString:string] ) return NO; 98 if( ! _addressRegex && _address && [_address length] && ! [_address isEqualToString:string] ) return NO; 93 99 94 100 string = [user realName]; 95 if( _realNameRegex && string && ! [_realNameRegex findInString:string] ) return NO; 96 if( ! _realNameRegex && _realName && string && [_realName length] && ! [_realName isEqualToString:string] ) return NO; 101 if( _realNameRegex && ! string ) return NO; 102 if( _realNameRegex && ! [_realNameRegex findInString:string] ) return NO; 103 if( ! _realNameRegex && _realName && [_realName length] && ! [_realName isEqualToString:string] ) return NO; 97 104 98 105 NSData *data = [user publicKey]; 99 if( _publicKey && data &&[_publicKey length] && ! [_publicKey isEqualToData:data] ) return NO;106 if( _publicKey && [_publicKey length] && ! [_publicKey isEqualToData:data] ) return NO; 100 107 101 108 @synchronized( _matchedChatUsers ) { … … 213 220 _interim = interim; 214 221 } 222 223 - (NSArray *) applicableServerDomains { 224 return [[_applicableServerDomains retain] autorelease]; 225 } 226 227 - (void) setApplicableServerDomains:(NSArray *) serverDomains { 228 id old = _applicableServerDomains; 229 _applicableServerDomains = [serverDomains copyWithZone:nil]; 230 [old release]; 231 } 215 232 @end trunk/Chat Core/MVIRCChatConnection.m
r3189 r3190 424 424 #pragma mark - 425 425 426 - (void) startWatchingUser:(MVChatUser *) user {427 NSParameterAssert( user != nil );428 NSParameterAssert( [[user nickname] length] > 0 );429 430 }431 432 - (void) stopWatchingUser:(MVChatUser *) user {433 NSParameterAssert( user != nil );434 NSParameterAssert( [[user nickname] length] > 0 );435 436 }437 438 426 - (void) addChatUserWatchRule:(MVChatUserWatchRule *) rule { 427 @synchronized( _chatUserWatchRules ) { 428 if( [_chatUserWatchRules containsObject:rule] ) return; 429 } 430 439 431 [super addChatUserWatchRule:rule]; 440 432 441 if( [self isConnected] && [rule nickname] && ! [rule nicknameIsRegularExpression] ) { 442 if( _watchCommandSupported ) [self sendRawMessageWithFormat:@"WATCH +%@", [rule nickname]]; 443 else [self sendRawMessageWithFormat:@"ISON %@", [rule nickname]]; 433 if( [rule nickname] && ! [rule nicknameIsRegularExpression] ) { 434 MVChatUser *user = [self chatUserWithUniqueIdentifier:[rule nickname]]; 435 [rule matchChatUser:user]; 436 if( [self isConnected] ) { 437 if( _watchCommandSupported ) [self sendRawMessageWithFormat:@"WATCH +%@", [rule nickname]]; 438 else [self sendRawMessageWithFormat:@"ISON %@", [rule nickname]]; 439 } 444 440 } 445 441 } … … 628 624 629 625 _isonSentCount = 0; 630 631 @synchronized( _knownUsers ) {632 [_knownUsers removeAllObjects];633 }634 626 635 627 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector( _periodicCleanUp ) object:nil]; trunk/Colloquy.xcodeproj/project.pbxproj
r3176 r3190 475 475 1C0A4CF40799BEA70093B702 /* JVViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVViewCell.h; path = Views/JVViewCell.h; sourceTree = "<group>"; }; 476 476 1C0A4CF50799BEA70093B702 /* JVViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JVViewCell.m; path = Views/JVViewCell.m; sourceTree = "<group>"; }; 477 1C0B2F0809DF8A8B009952E7 /* MVChatUserWatchRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MVChatUserWatchRule.h; path = "Chat Core/MVChatUserWatchRule.h"; sourceTree = "<group>"; }; 477 478 1C18CD100528DBBA000001C8 /* NSColorAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSColorAdditions.h; path = Additions/NSColorAdditions.h; sourceTree = "<group>"; }; 478 479 1C1ACE410533943900F71D4E /* JVInspectorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVInspectorController.h; path = Controllers/JVInspectorController.h; sourceTree = "<group>"; }; … … 1654 1655 1CDDCF830716208300FE11C3 /* MVChatRoom.h */, 1655 1656 1CDDCF840716208300FE11C3 /* MVChatUser.h */, 1657 1C0B2F0809DF8A8B009952E7 /* MVChatUserWatchRule.h */, 1656 1658 1C8CF8E1066530D60080A2F5 /* MVFileTransfer.h */, 1657 1659 1C2EF7EB0427A40B00000102 /* MVChatPluginManager.h */, trunk/Controllers/MVBuddyListController.m
r3072 r3190 233 233 [self showNewPersonSheet:nil]; 234 234 } else { 235 JVBuddy *buddy = [JVBuddy buddyWithPerson:person];236 [self _addBuddyToList:buddy];235 // JVBuddy *buddy = [JVBuddy buddyWithPerson:person]; 236 // [self _addBuddyToList:buddy]; 237 237 [self _saveBuddyList]; 238 238 } … … 338 338 339 339 if( person ) { 340 JVBuddy *buddy = [JVBuddy buddyWithPerson:person];341 [self _addBuddyToList:buddy];340 // JVBuddy *buddy = [JVBuddy buddyWithPerson:person]; 341 // [self _addBuddyToList:buddy]; 342 342 [self _saveBuddyList]; 343 343 } … … 974 974 975 975 - (void) _saveBuddyList { 976 NSMutableArray *list = [ NSMutableArray arrayWithCapacity:[_buddyList count]];976 NSMutableArray *list = [[NSMutableArray allocWithZone:nil] initWithCapacity:[_buddyList count]]; 977 977 NSEnumerator *enumerator = [_buddyList objectEnumerator]; 978 978 JVBuddy *buddy = nil; 979 979 980 980 while( ( buddy = [enumerator nextObject] ) ) 981 [list addObject:[buddy uniqueIdentifier]];982 983 [ [NSUserDefaults standardUserDefaults] setObject:list forKey:@"JVChatBuddies"];984 [ [NSUserDefaults standardUserDefaults] synchronize];981 [list addObject:[buddy dictionaryRepresentation]]; 982 983 [list writeToFile:[@"~/Library/Application Support/Colloquy/Buddy List.plist" stringByExpandingTildeInPath] atomically:YES]; 984 [list release]; 985 985 } 986 986 987 987 - (void) _loadBuddyList { 988 NSArray *list = [[NS UserDefaults standardUserDefaults] objectForKey:@"JVChatBuddies"];988 NSArray *list = [[NSArray allocWithZone:nil] initWithContentsOfFile:[@"~/Library/Application Support/Colloquy/Buddy List.plist" stringByExpandingTildeInPath]]; 989 989 NSEnumerator *enumerator = [list objectEnumerator]; 990 NSString *identifier = nil; 991 992 while( ( identifier = [enumerator nextObject] ) ) { 993 JVBuddy *buddy = [JVBuddy buddyWithUniqueIdentifier:identifier]; 994 if( [[buddy users] count] ) [self _addBuddyToList:buddy]; 995 } 990 NSDictionary *buddyDictionary = nil; 991 992 while( ( buddyDictionary = [enumerator nextObject] ) ) { 993 JVBuddy *buddy = [[JVBuddy allocWithZone:[self zone]] initWithDictionaryRepresentation:buddyDictionary]; 994 if( buddy ) [self _addBuddyToList:buddy]; 995 [buddy release]; 996 } 997 998 [list release]; 996 999 } 997 1000 @end trunk/Controllers/MVConnectionsController.m
r3147 r3190 559 559 560 560 while( ( info = [enumerator nextObject] ) ) { 561 if( [[(MVChatConnection *)[info objectForKey:@"connection"] server] c aseInsensitiveCompare:address] == NSOrderedSame ) {561 if( [[(MVChatConnection *)[info objectForKey:@"connection"] server] compare:address options:( NSCaseInsensitiveSearch | NSLiteralSearch | NSBackwardsSearch | NSAnchoredSearch )] == NSOrderedSame ) { 562 562 ret = [info objectForKey:@"connection"]; 563 563 if( [ret isConnected] ) return ret; … … 574 574 575 575 while( ( info = [enumerator nextObject] ) ) 576 if( [[(MVChatConnection *)[info objectForKey:@"connection"] server] c aseInsensitiveCompare:address] == NSOrderedSame )576 if( [[(MVChatConnection *)[info objectForKey:@"connection"] server] compare:address options:( NSCaseInsensitiveSearch | NSLiteralSearch | NSBackwardsSearch | NSAnchoredSearch )] == NSOrderedSame ) 577 577 [ret addObject:[info objectForKey:@"connection"]]; 578 578 trunk/Models/JVBuddy.h
r3072 r3190 10 10 11 11 @class ABPerson; 12 @class MVChatUserWatchRule; 12 13 13 14 extern NSString * const JVBuddyAddressBookIRCNicknameProperty; … … 22 23 @interface JVBuddy : NSObject { 23 24 ABPerson *_person; 25 NSMutableArray *_rules; 24 26 NSMutableArray *_users; 25 27 NSMutableSet *_onlineUsers; … … 29 31 + (void) setPreferredName:(JVBuddyName) preferred; 30 32 31 + (id) buddyWithPerson:(ABPerson *) person; 32 + (id) buddyWithUniqueIdentifier:(NSString *) identifier; 33 34 - (id) initWithPerson:(ABPerson *) person; 33 - (id) initWithDictionaryRepresentation:(NSDictionary *) dictionary; 34 - (NSDictionary *) dictionaryRepresentation; 35 35 36 36 - (void) registerWithApplicableConnections; … … 55 55 - (NSSet *) onlineUsers; 56 56 57 - (void) addUser:(MVChatUser *) user; 58 - (void) removeUser:(MVChatUser *) user; 59 - (void) replaceUser:(MVChatUser *) oldUser withUser:(MVChatUser *) newUser; 57 - (void) addWatchRule:(MVChatUserWatchRule *) rule; 58 - (void) removeWatchRule:(MVChatUserWatchRule *) rule; 60 59 61 60 - (NSImage *) picture; trunk/Models/JVBuddy.m
r3072 r3190 1 1 #import "JVBuddy.h" 2 3 #import <ChatCore/MVChatUserWatchRule.h> 2 4 #import "MVConnectionsController.h" 3 5 … … 28 30 } 29 31 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 { 32 #pragma mark - 33 34 - (id) initWithDictionaryRepresentation:(NSDictionary *) dictionary { 44 35 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( _buddyOnline: ) name:MVChatConnectionWatchedUserOnlineNotification object:nil]; 48 // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyAwayStatusChange: ) name:MVChatConnectionBuddyIsAwayNotification object:nil]; 49 // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyAwayStatusChange: ) name:MVChatConnectionBuddyIsUnawayNotification object:nil]; 50 51 _person = [person retain]; 36 _rules = [[NSMutableArray allocWithZone:nil] initWithCapacity:10]; 52 37 _users = [[NSMutableArray allocWithZone:nil] initWithCapacity:5]; 53 38 _onlineUsers = [[NSMutableSet allocWithZone:nil] initWithCapacity:5]; 54 39 _activeUser = nil; 55 40 56 ABMultiValue *value = [person valueForProperty:JVBuddyAddressBookIRCNicknameProperty]; 57 unsigned int i = 0, count = [value count]; 58 MVChatUser *user = nil; 59 60 for( i = 0; i < count; i++ ) { 61 user = [MVChatUser wildcardUserWithNicknameMask:[NSString stringWithFormat:@"%@@%@", [value valueAtIndex:i], [value labelAtIndex:i]] andHostMask:nil]; 62 [_users addObject:user]; 63 if( ! [self activeUser] ) [self setActiveUser:user]; 41 NSEnumerator *enumerator = [[dictionary objectForKey:@"rules"] objectEnumerator]; 42 NSDictionary *ruleDictionary = nil; 43 while( ( ruleDictionary = [enumerator nextObject] ) ) { 44 MVChatUserWatchRule *rule = [[MVChatUserWatchRule allocWithZone:[self zone]] initWithDictionaryRepresentation:ruleDictionary]; 45 if( rule ) [self addWatchRule:rule]; 46 [rule release]; 64 47 } 48 49 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _registerWithConnection: ) name:MVChatConnectionDidConnectNotification object:nil]; 50 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _disconnected: ) name:MVChatConnectionDidDisconnectNotification object:nil]; 65 51 66 52 [self registerWithApplicableConnections]; … … 76 62 77 63 [_person release]; 64 [_rules release]; 78 65 [_users release]; 79 66 [_onlineUsers release]; … … 82 69 _person = nil; 83 70 _users = nil; 71 _rules = nil; 84 72 _onlineUsers = nil; 85 73 _activeUser = nil; … … 90 78 #pragma mark - 91 79 80 - (NSDictionary *) dictionaryRepresentation { 81 NSMutableDictionary *dictionary = [[NSMutableDictionary allocWithZone:nil] initWithCapacity:5]; 82 [dictionary setObject:_rules forKey:@"rules"]; 83 return dictionary; 84 } 85 86 #pragma mark - 87 92 88 - (void) registerWithApplicableConnections { 93 NSEnumerator *enumerator = [_users objectEnumerator]; 94 NSEnumerator *connectionEnumerator = nil; 95 MVChatConnection *connection = nil; 96 MVChatUser *user = nil; 97 98 while( ( user = [enumerator nextObject] ) ) { 99 connectionEnumerator = [[[MVConnectionsController defaultController] connectionsForServerAddress:[user serverAddress]] objectEnumerator]; 100 while( ( connection = [connectionEnumerator nextObject] ) ) 101 [connection startWatchingUser:user]; 89 NSEnumerator *enumerator = [_rules objectEnumerator]; 90 MVChatUserWatchRule *rule = nil; 91 92 while( ( rule = [enumerator nextObject] ) ) { 93 if( [[rule applicableServerDomains] count] ) { 94 NSEnumerator *domainEnumerator = [[rule applicableServerDomains] objectEnumerator]; 95 NSString *domain = nil; 96 97 while( ( domain = [domainEnumerator nextObject] ) ) { 98 NSEnumerator *connectionEnumerator = [[[MVConnectionsController defaultController] connectionsForServerAddress:domain] objectEnumerator]; 99 MVChatConnection *connection = nil; 100 101 while( ( connection = [connectionEnumerator nextObject] ) ) 102 [connection addChatUserWatchRule:rule]; 103 } 104 } else { 105 NSEnumerator *connectionEnumerator = [[[MVConnectionsController defaultController] connections] objectEnumerator]; 106 MVChatConnection *connection = nil; 107 108 while( ( connection = [connectionEnumerator nextObject] ) ) 109 [connection addChatUserWatchRule:rule]; 110 } 102 111 } 103 112 } 104 113 105 114 - (void) unregisterWithApplicableConnections { 106 NSEnumerator *enumerator = [_users objectEnumerator]; 107 NSEnumerator *connectionEnumerator = nil; 108 MVChatConnection *connection = nil; 109 MVChatUser *user = nil; 110 111 while( ( user = [enumerator nextObject] ) ) { 112 connectionEnumerator = [[[MVConnectionsController defaultController] connectionsForServerAddress:[user serverAddress]] objectEnumerator]; 113 while( ( connection = [connectionEnumerator nextObject] ) ) 114 [connection stopWatchingUser:user]; 115 NSEnumerator *enumerator = [_rules objectEnumerator]; 116 MVChatUserWatchRule *rule = nil; 117 118 while( ( rule = [enumerator nextObject] ) ) { 119 if( [[rule applicableServerDomains] count] ) { 120 NSEnumerator *domainEnumerator = [[rule applicableServerDomains] objectEnumerator]; 121 NSString *domain = nil; 122 123 while( ( domain = [domainEnumerator nextObject] ) ) { 124 NSEnumerator *connectionEnumerator = [[[MVConnectionsController defaultController] connectionsForServerAddress:domain] objectEnumerator]; 125 MVChatConnection *connection = nil; 126 127 while( ( connection = [connectionEnumerator nextObject] ) ) 128 [connection removeChatUserWatchRule:rule]; 129 } 130 } else { 131 NSEnumerator *connectionEnumerator = [[[MVConnectionsController defaultController] connections] objectEnumerator]; 132 MVChatConnection *connection = nil; 133 134 while( ( connection = [connectionEnumerator nextObject] ) ) 135 [connection removeChatUserWatchRule:rule]; 136 } 115 137 } 116 138 } … … 123 145 124 146 - (void) setActiveUser:(MVChatUser *) user { 125 if( [user isWildcardUser] ) {126 NSEnumerator *enumerator = [_onlineUsers objectEnumerator];127 MVChatUser *match = nil;128 129 while( ( match = [enumerator nextObject] ) ) {130 if( [match isEqualToChatUser:user] ) {131 user = match;132 break;133 }134 }135 }136 137 147 [_activeUser autorelease]; 138 148 _activeUser = [user retain]; … … 202 212 #pragma mark - 203 213 204 - (void) addUser:(MVChatUser *) user { 205 if( [_users containsObject:user] ) return; 206 207 ABMutableMultiValue *value = [[[_person valueForProperty:JVBuddyAddressBookIRCNicknameProperty] mutableCopy] autorelease]; 208 [value addValue:[user nickname] withLabel:[user serverAddress]]; 209 [_person setValue:value forProperty:JVBuddyAddressBookIRCNicknameProperty]; 210 211 if( ! [_users count] || ! [self activeUser] ) 212 [self setActiveUser:user]; 213 214 [_users addObject:user]; 215 216 [[ABAddressBook sharedAddressBook] save]; 217 218 [self registerWithApplicableConnections]; 219 } 220 221 - (void) removeUser:(MVChatUser *) user { 222 if( ! [_users containsObject:user] ) return; 223 224 ABMutableMultiValue *value = [[[_person valueForProperty:JVBuddyAddressBookIRCNicknameProperty] mutableCopy] autorelease]; 225 int i = 0, count = [value count]; 226 227 for( i = count - 1; i >= 0; i-- ) 228 if( [[user nickname] caseInsensitiveCompare:[value valueAtIndex:i]] == NSOrderedSame && [[user serverAddress] caseInsensitiveCompare:[value labelAtIndex:i]] == NSOrderedSame ) 229 [value removeValueAndLabelAtIndex:i]; 230 231 [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:user]; 232 233 [_users removeObject:user]; 234 235 NSArray *online = [_onlineUsers allObjects]; 236 unsigned int index = [online indexOfObject:user]; 237 if( index != NSNotFound ) [_onlineUsers removeObject:[online objectAtIndex:index]]; 238 239 [_person setValue:value forProperty:JVBuddyAddressBookIRCNicknameProperty]; 240 241 if( [[self activeUser] isEqualToChatUser:user] ) 242 [self setActiveUser:( [_onlineUsers count] ? [_onlineUsers anyObject] : [_users lastObject] )]; 243 244 [[ABAddressBook sharedAddressBook] save]; 245 } 246 247 - (void) replaceUser:(MVChatUser *) oldUser withUser:(MVChatUser *) newUser { 248 [self removeUser:oldUser]; 249 [self addUser:newUser]; 214 - (void) addWatchRule:(MVChatUserWatchRule *) rule { 215 if( [_rules containsObject:rule] ) return; 216 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _ruleMatched: ) name:MVChatUserWatchRuleMatchedNotification object:rule]; 217 [_rules addObject:rule]; 218 } 219 220 - (void) removeWatchRule:(MVChatUserWatchRule *) rule { 221 if( ! [_rules containsObject:rule] ) return; 222 [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserWatchRuleMatchedNotification object:rule]; 223 [_rules removeObject:rule]; 250 224 } 251 225 … … 345 319 346 320 - (void) editInAddressBook { 321 if( ! _person ) return; 347 322 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"addressbook://%@?edit", [_person uniqueId]]]; 348 323 [[NSWorkspace sharedWorkspace] openURL:url]; … … 350 325 351 326 - (void) viewInAddressBook { 327 if( ! _person ) return; 352 328 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"addressbook://%@", [_person uniqueId]]]; 353 329 [[NSWorkspace sharedWorkspace] openURL:url]; … … 442 418 - (void) _buddyOnline:(NSNotification *) notification { 443 419 MVChatUser *user = [notification object]; 444 if( [_users containsObject:user] ) { 445 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOffline: ) name:MVChatConnectionWatchedUserOfflineNotification object:user]; 446 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyIdleUpdate: ) name:MVChatUserIdleTimeUpdatedNotification object:user]; 447 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyStatusChanged: ) name:MVChatUserStatusChangedNotification object:user]; 448 449 BOOL cameOnline = ( ! [_onlineUsers count] ? YES : NO ); 450 [_onlineUsers addObject:user]; 451 452 if( [self status] != MVChatUserAvailableStatus || [self status] != MVChatUserAwayStatus ) [self setActiveUser:user]; 453 if( cameOnline ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyCameOnlineNotification object:self userInfo:nil]; 454 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyUserCameOnlineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 455 } 420 BOOL cameOnline = ( ! [_onlineUsers count] ? YES : NO ); 421 [_onlineUsers addObject:user]; 422 423 if( [self status] != MVChatUserAvailableStatus || [self status] != MVChatUserAwayStatus ) [self setActiveUser:user]; 424 if( cameOnline ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyCameOnlineNotification object:self userInfo:nil]; 425 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyUserCameOnlineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 456 426 } 457 427 458 428 - (void) _buddyOffline:(NSNotification *) notification { 459 429 MVChatUser *user = [notification object]; 460 [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:user];461 430 462 431 [_onlineUsers removeObject:user]; … … 486 455 - (void) _registerWithConnection:(NSNotification *) notification { 487 456 MVChatConnection *connection = [notification object]; 488 NSEnumerator *enumerator = [_users objectEnumerator]; 457 NSEnumerator *enumerator = [_rules objectEnumerator]; 458 MVChatUserWatchRule *rule = nil; 459 460 while( ( rule = [enumerator nextObject] ) ) { 461 if( [[rule applicableServerDomains] count] ) { 462 NSEnumerator *domainEnumerator = [[rule applicableServerDomains] objectEnumerator]; 463 NSString *domain = nil; 464 465 while( ( domain = [domainEnumerator nextObject] ) ) { 466 if( [[connection server] compare:domain options:( NSCaseInsensitiveSearch | NSLiteralSearch | NSBackwardsSearch | NSAnchoredSearch )] == NSOrderedSame ) 467 [connection addChatUserWatchRule:rule]; 468 } 469 } else [connection addChatUserWatchRule:rule]; 470 } 471 } 472 473 - (void) _disconnected:(NSNotification *) notification { 474 MVChatConnection *connection = [notification object]; 475 NSEnumerator *enumerator = [[[_onlineUsers copy] autorelease] objectEnumerator]; 489 476 MVChatUser *user = nil; 490 477 491 478 while( ( user = [enumerator nextObject] ) ) { 492 if( [[user connection] isEqual:connection] || [[user serverAddress] caseInsensitiveCompare:[connection server]] == NSOrderedSame ) { 493 [connection startWatchingUser:user]; 494 } 495 } 496 } 497 498 - (void) _disconnected:(NSNotification *) notification { 499 NSEnumerator *enumerator = [[[MVConnectionsController defaultController] connections] objectEnumerator]; 500 MVChatConnection *connection = nil; 501 unsigned int count = 0; 502 503 while( ( connection = [enumerator nextObject] ) ) 504 if( [[connection server] caseInsensitiveCompare:[connection server]] == NSOrderedSame && [connection isConnected] ) 505 count++; 506 507 if( count >= 1 ) return; 508 509 connection = [notification object]; 510 enumerator = [[[_onlineUsers copy] autorelease] objectEnumerator]; 511 MVChatUser *user = nil; 512 513 while( ( user = [enumerator nextObject] ) ) { 514 if( [[user connection] isEqual:connection] || [[user serverAddress] caseInsensitiveCompare:[connection server]] == NSOrderedSame ) { 479 if( [[user connection] isEqual:connection] ) { 515 480 [_onlineUsers removeObject:user]; 516 481 if( ! [_onlineUsers count] ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyWentOfflineNotification object:self userInfo:nil]; 517 482 } 518 483 } 484 } 485 486 - (void) _ruleMatched:(NSNotification *) notification { 487 MVChatUser *user = [[notification userInfo] objectForKey:@"user"]; 488 489 [_users addObject:user]; 490 if( ! [self activeUser] ) 491 [self setActiveUser:user]; 492 493 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOnline: ) name:MVChatConnectionWatchedUserOfflineNotification object:user]; 494 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOffline: ) name:MVChatConnectionWatchedUserOfflineNotification object:user]; 495 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyIdleUpdate: ) name:MVChatUserIdleTimeUpdatedNotification object:user]; 496 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyStatusChanged: ) name:MVChatUserStatusChangedNotification object:user]; 519 497 } 520 498 @end
