Changeset 3498
- Timestamp:
- 12/28/06 16:18:57 (2 years ago)
- Files:
-
- trunk/Chat Core.exp (modified) (1 diff)
- trunk/Chat Core/MVChatConnection.h (modified) (1 diff)
- trunk/Chat Core/MVChatConnection.m (modified) (4 diffs)
- trunk/Chat Core/MVChatConnectionPrivate.h (modified) (1 diff)
- trunk/Chat Core/MVChatUser.h (modified) (2 diffs)
- trunk/Chat Core/MVChatUser.m (modified) (3 diffs)
- trunk/Chat Core/MVChatUserPrivate.h (modified) (1 diff)
- trunk/Chat Core/MVChatUserWatchRule.h (modified) (2 diffs)
- trunk/Chat Core/MVChatUserWatchRule.m (modified) (5 diffs)
- trunk/Chat Core/MVIRCChatConnection.h (modified) (1 diff)
- trunk/Chat Core/MVIRCChatConnection.m (modified) (27 diffs)
- trunk/Models/JVBuddy.m (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Chat Core.exp
r3496 r3498 80 80 _MVChatUserAttributeUpdatedNotification 81 81 _MVChatUserWatchRuleMatchedNotification 82 _MVChatUserWatchRuleRemovedMatchedUserNotification 82 83 _MVDownloadFileTransferOfferNotification 83 84 _MVFileTransferStartedNotification trunk/Chat Core/MVChatConnection.h
r3496 r3498 72 72 extern NSString *MVChatConnectionSelfAwayStatusChangedNotification; 73 73 74 extern NSString *MVChatConnectionWatchedUserOnlineNotification;75 extern NSString *MVChatConnectionWatchedUserOfflineNotification;76 77 74 extern NSString *MVChatConnectionNicknameAcceptedNotification; 78 75 extern NSString *MVChatConnectionNicknameRejectedNotification; trunk/Chat Core/MVChatConnection.m
r3496 r3498 671 671 - (void) addChatUserWatchRule:(MVChatUserWatchRule *) rule { 672 672 NSParameterAssert( rule != nil ); 673 673 674 if( ! _chatUserWatchRules ) 674 675 _chatUserWatchRules = [[NSMutableSet allocWithZone:nil] initWithCapacity:10]; 676 675 677 @synchronized( _chatUserWatchRules ) { 676 678 if( ! [_chatUserWatchRules containsObject:rule] ) … … 681 683 - (void) removeChatUserWatchRule:(MVChatUserWatchRule *) rule { 682 684 NSParameterAssert( rule != nil ); 685 686 [rule removeMatchedUsersForConnection:self]; 687 683 688 @synchronized( _chatUserWatchRules ) { 684 689 [_chatUserWatchRules removeObject:rule]; … … 919 924 } 920 925 921 - (void) _sendPossibleOnlineNotificationForUser:(MVChatUser *) user { 922 if( [user _onlineNotificationSent] ) return; 923 if( [user isWatched] || [self _watchRulesMatchingUser:user] ) { 924 [user _setOnlineNotificationSent:YES]; 925 [user _setDateDisconnected:nil]; 926 if( [user status] != MVChatUserAwayStatus ) 927 [user _setStatus:MVChatUserAvailableStatus]; 928 if( ! [user dateDisconnected] ) 929 [user _setDateConnected:[NSDate date]]; 930 931 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatConnectionWatchedUserOnlineNotification object:user userInfo:nil]; 932 } 933 } 934 935 - (void) _sendPossibleOfflineNotificationForUser:(MVChatUser *) user { 936 if( ! [user _onlineNotificationSent] ) return; 937 if( [user isWatched] ) { 938 [user _setOnlineNotificationSent:NO]; 939 [user _setWatched:NO]; 940 941 if( ! [user dateDisconnected] ) 942 [user _setDateDisconnected:[NSDate date]]; 943 [user _setStatus:MVChatUserOfflineStatus]; 944 926 - (void) _markUserAsOnline:(MVChatUser *) user { 927 [user _setDateDisconnected:nil]; 928 929 if( ! [user dateConnected] ) 930 [user _setDateConnected:[NSDate date]]; 931 932 if( [user status] != MVChatUserAwayStatus ) 933 [user _setStatus:MVChatUserAvailableStatus]; 934 935 [self _watchRulesMatchingUser:user]; 936 } 937 938 - (void) _markUserAsOffline:(MVChatUser *) user { 939 if( ! [user dateDisconnected] && [user dateConnected] ) 940 [user _setDateDisconnected:[NSDate date]]; 941 942 if( [user status] != MVChatUserOfflineStatus ) { 945 943 [user retain]; // retain since removeMatchedUser might hold the last reference 946 944 … … 952 950 } 953 951 954 [ [NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatConnectionWatchedUserOfflineNotification object:user userInfo:nil];952 [user _setStatus:MVChatUserOfflineStatus]; 955 953 956 954 [user release]; trunk/Chat Core/MVChatConnectionPrivate.h
r3349 r3498 21 21 22 22 - (unsigned int) _watchRulesMatchingUser:(MVChatUser *) user; 23 - (void) _ sendPossibleOnlineNotificationForUser:(MVChatUser *) user;24 - (void) _ sendPossibleOfflineNotificationForUser:(MVChatUser *) user;23 - (void) _markUserAsOnline:(MVChatUser *) user; 24 - (void) _markUserAsOffline:(MVChatUser *) user; 25 25 @end trunk/Chat Core/MVChatUser.h
r3456 r3498 76 76 BOOL _identified : 1; 77 77 BOOL _serverOperator : 1; 78 BOOL _watched : 1;79 78 BOOL _onlineNotificationSent : 1; 80 79 } … … 161 160 - (BOOL) isIdentified; 162 161 - (BOOL) isServerOperator; 163 - (BOOL) isWatched;164 162 165 163 - (BOOL) isEqual:(id) object; trunk/Chat Core/MVChatUser.m
r3457 r3498 165 165 @property(readonly, getter=isIdentified) BOOL identified; 166 166 @property(readonly, getter=isServerOperator) BOOL serverOperator; 167 @property(readonly, getter=isWatched) BOOL watched;168 167 #endif 169 168 … … 174 173 - (BOOL) isServerOperator { 175 174 return _serverOperator; 176 }177 178 - (BOOL) isWatched {179 return _watched;180 175 } 181 176 … … 510 505 } 511 506 512 - (void) _setWatched:(BOOL) isWatched {513 _watched = isWatched;514 }515 516 507 - (void) _setIdleTime:(NSTimeInterval) time { 517 508 _idleTime = time; trunk/Chat Core/MVChatUserPrivate.h
r3420 r3498 12 12 - (void) _setServerOperator:(BOOL) operator; 13 13 - (void) _setIdentified:(BOOL) identified; 14 - (void) _setWatched:(BOOL) watched;15 14 - (void) _setIdleTime:(NSTimeInterval) time; 16 15 - (void) _setStatus:(MVChatUserStatus) status; trunk/Chat Core/MVChatUserWatchRule.h
r3455 r3498 1 1 @class MVChatUser; 2 @class MVChatConnection; 2 3 @class AGRegex; 3 4 4 5 extern NSString *MVChatUserWatchRuleMatchedNotification; 6 extern NSString *MVChatUserWatchRuleRemovedMatchedUserNotification; 5 7 6 8 @interface MVChatUserWatchRule : NSObject <NSCopying> { … … 25 27 - (BOOL) matchChatUser:(MVChatUser *) user; 26 28 - (void) removeMatchedUser:(MVChatUser *) user; 29 - (void) removeMatchedUsersForConnection:(MVChatConnection *) connection; 27 30 28 31 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 trunk/Chat Core/MVChatUserWatchRule.m
r3484 r3498 7 7 8 8 NSString *MVChatUserWatchRuleMatchedNotification = @"MVChatUserWatchRuleMatchedNotification"; 9 NSString *MVChatUserWatchRuleRemovedMatchedUserNotification = @"MVChatUserWatchRuleRemovedMatchedUserNotification"; 9 10 10 11 @implementation MVChatUserWatchRule … … 23 24 } 24 25 26 - (void) dealloc { 27 [_matchedChatUsers release]; 28 [_nickname release]; 29 [_nicknameRegex release]; 30 [_realName release]; 31 [_realNameRegex release]; 32 [_username release]; 33 [_usernameRegex release]; 34 [_address release]; 35 [_addressRegex release]; 36 [_publicKey release]; 37 [_applicableServerDomains release]; 38 39 _matchedChatUsers = nil; 40 _nickname = nil; 41 _nicknameRegex = nil; 42 _realName = nil; 43 _realNameRegex = nil; 44 _username = nil; 45 _usernameRegex = nil; 46 _address = nil; 47 _addressRegex = nil; 48 _publicKey = nil; 49 _applicableServerDomains = nil; 50 51 [super dealloc]; 52 } 53 25 54 - (id) copyWithZone:(NSZone *) zone { 26 55 MVChatUserWatchRule *copy = [[MVChatUserWatchRule allocWithZone:zone] init]; … … 78 107 if( ! user ) return NO; 79 108 109 if( ! _matchedChatUsers ) 110 _matchedChatUsers = [[NSMutableSet allocWithZone:nil] initWithCapacity:10]; 111 80 112 @synchronized( _matchedChatUsers ) { 81 113 if( [_matchedChatUsers containsObject:user] ) … … 108 140 @synchronized( _matchedChatUsers ) { 109 141 if( ! [_matchedChatUsers containsObject:user] ) { 110 [user _setWatched:YES];111 142 [_matchedChatUsers addObject:user]; 112 143 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatUserWatchRuleMatchedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; … … 125 156 - (void) removeMatchedUser:(MVChatUser *) user { 126 157 @synchronized( _matchedChatUsers ) { 127 [_matchedChatUsers removeObject:user]; 158 if( [_matchedChatUsers containsObject:user] ) { 159 [user retain]; 160 [_matchedChatUsers removeObject:user]; 161 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatUserWatchRuleRemovedMatchedUserNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 162 [user release]; 163 } 164 } 165 } 166 167 - (void) removeMatchedUsersForConnection:(MVChatConnection *) connection { 168 @synchronized( _matchedChatUsers ) { 169 NSEnumerator *enumerator = [[[_matchedChatUsers copy] autorelease] objectEnumerator]; 170 MVChatUser *user = nil; 171 172 while( ( user = [enumerator nextObject] ) ) { 173 if( [[user connection] isEqual:connection] ) { 174 [user retain]; 175 [_matchedChatUsers removeObject:user]; 176 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatUserWatchRuleRemovedMatchedUserNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 177 [user release]; 178 } 179 } 128 180 } 129 181 } trunk/Chat Core/MVIRCChatConnection.h
r3228 r3498 16 16 NSMutableArray *_sendQueue; 17 17 NSMutableDictionary *_knownUsers; 18 NSMutableSet *_matchedUsers;19 18 NSMutableSet *_pendingWhoisUsers; 20 19 NSMutableSet *_fileTransfers; trunk/Chat Core/MVIRCChatConnection.m
r3483 r3498 139 139 [_queueWait release]; 140 140 [_lastCommand release]; 141 [_matchedUsers release];142 141 [_pendingWhoisUsers release]; 143 142 [_roomPrefixes release]; … … 163 162 _queueWait = nil; 164 163 _lastCommand = nil; 165 _matchedUsers = nil;166 164 _pendingWhoisUsers = nil; 167 165 _roomPrefixes = nil; … … 482 480 if( _watchCommandSupported ) [self sendRawMessageWithFormat:@"WATCH +%@", [rule nickname]]; 483 481 else [self sendRawMessageWithFormat:@"ISON %@", [rule nickname]]; 482 } 483 } else { 484 @synchronized( _knownUsers ) { 485 NSEnumerator *enumerator = [_knownUsers objectEnumerator]; 486 MVChatUser *user = nil; 487 while( ( user = [enumerator nextObject] ) ) 488 [rule matchChatUser:user]; 484 489 } 485 490 } … … 686 691 [old release]; 687 692 688 old = _matchedUsers;689 _matchedUsers = nil;690 [old release];691 692 693 old = _pendingWhoisUsers; 693 694 _pendingWhoisUsers = nil; … … 708 709 709 710 [self performSelectorOnMainThread:@selector( _didDisconnect ) withObject:nil waitUntilDone:NO]; 711 } 712 713 @synchronized( _knownUsers ) { 714 NSEnumerator *enumerator = [_knownUsers objectEnumerator]; 715 MVChatUser *user = nil; 716 717 while( ( user = [enumerator nextObject] ) ) 718 [user _setStatus:MVChatUserUnknownStatus]; 719 } 720 721 @synchronized( _chatUserWatchRules ) { 722 NSEnumerator *enumerator = [_chatUserWatchRules objectEnumerator]; 723 MVChatUserWatchRule *rule = nil; 724 while( ( rule = [enumerator nextObject] ) ) 725 [rule removeMatchedUsersForConnection:self]; 710 726 } 711 727 } … … 1115 1131 #pragma mark - 1116 1132 1117 - (unsigned int) _watchRulesMatchingUser:(MVChatUser *) user {1118 if( ! _matchedUsers )1119 _matchedUsers = [[NSMutableSet allocWithZone:nil] initWithCapacity:25];1120 1121 unsigned int count = 0;1122 @synchronized( _chatUserWatchRules ) {1123 NSEnumerator *enumerator = [_chatUserWatchRules objectEnumerator];1124 MVChatUserWatchRule *rule = nil;1125 while( ( rule = [enumerator nextObject] ) ) {1126 if( [rule matchChatUser:user] ) {1127 count++;1128 @synchronized( _matchedUsers ) {1129 [_matchedUsers addObject:user];1130 }1131 }1132 }1133 }1134 1135 return count;1136 }1137 1138 - (void) _sendPossibleOfflineNotificationForUser:(MVChatUser *) user {1139 @synchronized( _matchedUsers ) {1140 if( [user isWatched] ) [_matchedUsers removeObject:user];1141 }1142 1143 [super _sendPossibleOfflineNotificationForUser:user];1144 }1145 1146 1133 - (void) _scheduleWhoisForUser:(MVChatUser *) user { 1147 1134 if( ! _pendingWhoisUsers ) … … 1162 1149 [self performSelector:@selector( _whoisWatchedUsers ) withObject:nil afterDelay:JVWatchedUserWHOISDelay]; 1163 1150 1164 @synchronized( _matchedUsers ) { 1165 if( ! [_matchedUsers count] ) return; // nothing to do, return and wait until the next scheduled fire 1166 1167 NSEnumerator *enumerator = [_matchedUsers objectEnumerator]; 1168 MVChatUser *user = nil; 1169 while( ( user = [enumerator nextObject] ) ) 1170 [self _scheduleWhoisForUser:user]; 1171 } 1151 NSMutableSet *matchedUsers = [NSMutableSet set]; 1152 @synchronized( _chatUserWatchRules ) { 1153 if( ! [_chatUserWatchRules count] ) return; // nothing to do, return and wait until the next scheduled fire 1154 1155 NSEnumerator *enumerator = [_chatUserWatchRules objectEnumerator]; 1156 MVChatUserWatchRule *rule = nil; 1157 while( ( rule = [enumerator nextObject] ) ) 1158 [matchedUsers unionSet:[rule matchedChatUsers]]; 1159 } 1160 1161 NSEnumerator *enumerator = [matchedUsers objectEnumerator]; 1162 MVChatUser *user = nil; 1163 while( ( user = [enumerator nextObject] ) ) 1164 [self _scheduleWhoisForUser:user]; 1172 1165 } 1173 1166 … … 1179 1172 if( [_lastSentIsonNicknames count] ) return; // there is already pending ISON requests, skip this round to catch up 1180 1173 1181 @synchronized( _matchedUsers ) { 1182 @synchronized( _chatUserWatchRules ) { 1183 if( ! [_matchedUsers count] && ! [_chatUserWatchRules count] ) 1184 return; // nothing to do, return and wait until the next scheduled fire 1185 } 1174 NSMutableSet *matchedUsers = [NSMutableSet set]; 1175 @synchronized( _chatUserWatchRules ) { 1176 if( ! [_chatUserWatchRules count] ) return; // nothing to do, return and wait until the next scheduled fire 1177 1178 NSEnumerator *enumerator = [_chatUserWatchRules objectEnumerator]; 1179 MVChatUserWatchRule *rule = nil; 1180 while( ( rule = [enumerator nextObject] ) ) 1181 [matchedUsers unionSet:[rule matchedChatUsers]]; 1186 1182 } 1187 1183 … … 1192 1188 1193 1189 [_lastSentIsonNicknames release]; 1194 _lastSentIsonNicknames = [[NSMutableSet allocWithZone:nil] initWithCapacity:[_chatUserWatchRules count]]; 1195 1196 @synchronized( _matchedUsers ) { 1197 NSEnumerator *enumerator = [_matchedUsers objectEnumerator]; 1198 MVChatUser *user = nil; 1199 1200 while( ( user = [enumerator nextObject] ) ) { 1201 NSString *nick = [user nickname]; 1202 if( ( [nick length] + [request length] ) > 510 ) { 1203 [self sendRawMessage:request]; 1204 [request release]; 1205 _isonSentCount++; 1206 1207 request = [[NSMutableString allocWithZone:nil] initWithCapacity:510]; 1208 [request setString:@"ISON "]; 1209 } 1210 1211 [request appendString:nick]; 1212 [request appendString:@" "]; 1213 1214 [_lastSentIsonNicknames addObject:nick]; 1215 } 1190 _lastSentIsonNicknames = [[NSMutableSet allocWithZone:nil] initWithCapacity:( [_chatUserWatchRules count] * 5 )]; 1191 1192 NSEnumerator *enumerator = [matchedUsers objectEnumerator]; 1193 MVChatUser *user = nil; 1194 1195 while( ( user = [enumerator nextObject] ) ) { 1196 NSString *nick = [user nickname]; 1197 if( ( [nick length] + [request length] ) > 510 ) { 1198 [self sendRawMessage:request]; 1199 [request release]; 1200 _isonSentCount++; 1201 1202 request = [[NSMutableString allocWithZone:nil] initWithCapacity:510]; 1203 [request setString:@"ISON "]; 1204 } 1205 1206 [request appendString:nick]; 1207 [request appendString:@" "]; 1208 1209 [_lastSentIsonNicknames addObject:nick]; 1216 1210 } 1217 1211 … … 1222 1216 while( ( rule = [enumerator nextObject] ) ) { 1223 1217 NSString *nick = [rule nickname]; 1224 if( nick&& ! [rule nicknameIsRegularExpression] && ! [_lastSentIsonNicknames containsObject:nick] ) {1218 if( [nick length] && ! [rule nicknameIsRegularExpression] && ! [_lastSentIsonNicknames containsObject:nick] ) { 1225 1219 if( ( [nick length] + [request length] ) > 510 ) { 1226 1220 [self sendRawMessage:request]; … … 1454 1448 BOOL ctcp = ( *bytes == '\001' && [msgData length] > 2 ); 1455 1449 1456 if( [sender status] != MVChatUserAwayStatus )1457 [sender _setStatus:MVChatUserAvailableStatus];1458 1450 [sender _setIdleTime:0.]; 1451 [self _markUserAsOnline:sender]; 1459 1452 1460 1453 if( [[self chatRoomNamePrefixes] characterIsMember:[targetName characterAtIndex:0]] ) { … … 1757 1750 [room _clearBannedUsers]; 1758 1751 } else { 1759 if( [sender status] != MVChatUserAwayStatus )1760 [sender _setStatus:MVChatUserAvailableStatus];1761 1752 [sender _setIdleTime:0.]; 1753 [self _markUserAsOnline:sender]; 1762 1754 [room _addMemberUser:sender]; 1763 1755 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatRoomUserJoinedNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", nil]]; 1764 [self _sendPossibleOnlineNotificationForUser:sender];1765 1756 } 1766 1757 } … … 1788 1779 if( [sender isLocalUser] ) return; 1789 1780 1790 [se nder _setDateDisconnected:[NSDate date]];1791 [ sender _setStatus:MVChatUserOfflineStatus];1781 [self _markUserAsOffline:sender]; 1782 [_pendingWhoisUsers removeObject:sender]; 1792 1783 1793 1784 NSData *reason = [parameters objectAtIndex:0]; … … 1804 1795 1805 1796 [info release]; 1806 1807 [self _sendPossibleOfflineNotificationForUser:sender];1808 1809 [_pendingWhoisUsers removeObject:sender];1810 1797 } 1811 1798 } … … 2007 1994 - (void) _handlePingWithParameters:(NSArray *) parameters fromSender:(id) sender { 2008 1995 if( [parameters count] >= 1 ) { 2009 if( [parameters count] == 1 ) [self sendRawMessageImmediatelyWithComponents:@"PONG :", [parameters objectAtIndex:0], nil]; 1996 if( [parameters count] == 1 ) 1997 [self sendRawMessageImmediatelyWithComponents:@"PONG :", [parameters objectAtIndex:0], nil]; 2010 1998 else [self sendRawMessageImmediatelyWithComponents:@"PONG ", [parameters objectAtIndex:1], @" :", [parameters objectAtIndex:0], nil]; 2011 if( [sender isKindOfClass:[MVChatUser class]] ) [self _sendPossibleOnlineNotificationForUser:sender]; 1999 2000 if( [sender isKindOfClass:[MVChatUser class]] ) 2001 [self _markUserAsOnline:sender]; 2012 2002 } 2013 2003 } … … 2021 2011 if( [parameters count] == 2 && [sender isKindOfClass:[MVChatUser class]] ) { 2022 2012 NSString *roomName = [self _stringFromPossibleData:[parameters objectAtIndex:1]]; 2013 [self _markUserAsOnline:sender]; 2023 2014 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatRoomInvitedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", roomName, @"room", nil]]; 2024 [self _sendPossibleOnlineNotificationForUser:sender];2025 2015 } 2026 2016 } … … 2032 2022 NSString *oldIdentifier = [[sender uniqueIdentifier] retain]; 2033 2023 2034 if( [sender status] != MVChatUserAwayStatus )2035 [sender _setStatus:MVChatUserAvailableStatus];2036 2024 [sender _setIdleTime:0.]; 2025 [self _markUserAsOnline:sender]; 2037 2026 2038 2027 NSNotification *note = nil; … … 2059 2048 [oldNickname release]; 2060 2049 [oldIdentifier release]; 2061 2062 [self _sendPossibleOnlineNotificationForUser:sender];2063 2050 } 2064 2051 } … … 2080 2067 if( [[user dateUpdated] timeIntervalSinceNow] < -JVWatchedUserWHOISDelay || ! [user dateUpdated] ) 2081 2068 [self _scheduleWhoisForUser:user]; 2082 2083 [self _sendPossibleOnlineNotificationForUser:user]; 2069 [self _markUserAsOnline:user]; 2084 2070 [_lastSentIsonNicknames removeObject:nick]; 2085 2071 } … … 2090 2076 while( ( nick = [enumerator nextObject] ) ) { 2091 2077 MVChatUser *user = [self chatUserWithUniqueIdentifier:nick]; 2092 [self _ sendPossibleOfflineNotificationForUser:user];2078 [self _markUserAsOffline:user]; 2093 2079 } 2094 2080 … … 2157 2143 [room _addMemberUser:member]; 2158 2144 [room _setModes:modes forMemberUser:member]; 2145 2146 [self _markUserAsOnline:member]; 2159 2147 } 2160 2148 … … 2211 2199 } 2212 2200 2213 [self _ sendPossibleOnlineNotificationForUser:member];2201 [self _markUserAsOnline:member]; 2214 2202 } 2215 2203 } … … 2294 2282 if( [parameters count] == 6 ) { 2295 2283 MVChatUser *user = [self chatUserWithUniqueIdentifier:[parameters objectAtIndex:1]]; 2296 [user _setServerOperator:NO]; // set these to NO now so we get the true values later in the WHOIS2297 2284 [user _setUsername:[parameters objectAtIndex:2]]; 2298 2285 [user _setAddress:[parameters objectAtIndex:3]]; 2299 2286 [user _setRealName:[self _stringFromPossibleData:[parameters objectAtIndex:5]]]; 2300 [user _set DateDisconnected:nil];2301 [user _set AwayStatusMessage:nil]; // set this to nil, we will get it if we get a 3012302 2303 [self _ sendPossibleOnlineNotificationForUser:user];2287 [user _setAwayStatusMessage:nil]; // set this to nil, we will get it if we get a RPL_AWAY 2288 [user _setServerOperator:NO]; // set this to NO now so we get the true values later in the RPL_WHOISOPERATOR 2289 2290 [self _markUserAsOnline:user]; 2304 2291 } 2305 2292 } … … 2339 2326 MVChatUser *user = [self chatUserWithUniqueIdentifier:[parameters objectAtIndex:1]]; 2340 2327 [user _setDateUpdated:[NSDate date]]; 2341 2342 if( [user status] != MVChatUserAwayStatus )2343 [user _setStatus:MVChatUserAvailableStatus];2344 2328 2345 2329 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatUserInformationUpdatedNotification object:user userInfo:nil]; … … 2398 2382 if( [parameters count] >= 2 ) { 2399 2383 MVChatUser *user = [self chatUserWithUniqueIdentifier:[parameters objectAtIndex:1]]; 2400 [self _ sendPossibleOfflineNotificationForUser:user];2384 [self _markUserAsOffline:user]; 2401 2385 if( [_pendingWhoisUsers containsObject:user] ) { 2402 2386 [_pendingWhoisUsers removeObject:user]; … … 2410 2394 if( [parameters count] >= 2 ) { 2411 2395 MVChatUser *user = [self chatUserWithUniqueIdentifier:[parameters objectAtIndex:1]]; 2412 [self _ sendPossibleOfflineNotificationForUser:user];2396 [self _markUserAsOffline:user]; 2413 2397 if( [_pendingWhoisUsers containsObject:user] ) { 2414 2398 [_pendingWhoisUsers removeObject:user]; … … 2438 2422 [user _setUsername:[parameters objectAtIndex:2]]; 2439 2423 [user _setAddress:[parameters objectAtIndex:3]]; 2440 [user _setDateDisconnected:nil]; 2441 2442 [self _sendPossibleOnlineNotificationForUser:user]; 2424 2425 [self _markUserAsOnline:user]; 2443 2426 2444 2427 if( [[user dateUpdated] timeIntervalSinceNow] < -JVWatchedUserWHOISDelay || ! [user dateUpdated] ) trunk/Models/JVBuddy.m
r3491 r3498 227 227 while( ( rule = [enumerator nextObject] ) ) 228 228 [connection removeChatUserWatchRule:rule]; 229 230 enumerator = [[[_users copy] autorelease] objectEnumerator]; 231 MVChatUser *user = nil; 232 233 while( ( user = [enumerator nextObject] ) ) 234 if( [[user connection] isEqual:connection] ) 235 [_users removeObject:user]; 236 237 if( [[[self activeUser] connection] isEqual:connection] ) 238 [self setActiveUser:[_users anyObject]]; 229 239 } 230 240 … … 240 250 [connection removeChatUserWatchRule:rule]; 241 251 } 252 253 [_users removeAllObjects]; 254 [self setActiveUser:nil]; 242 255 } 243 256 … … 321 334 if( [_rules containsObject:rule] ) return; 322 335 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _ruleMatched: ) name:MVChatUserWatchRuleMatchedNotification object:rule]; 336 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _ruleUserRemoved: ) name:MVChatUserWatchRuleRemovedMatchedUserNotification object:rule]; 323 337 [_rules addObject:rule]; 324 338 } … … 327 341 if( ! [_rules containsObject:rule] ) return; 328 342 [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserWatchRuleMatchedNotification object:rule]; 343 [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserWatchRuleRemovedMatchedUserNotification object:rule]; 329 344 [_rules removeObject:rule]; 330 345 } … … 545 560 546 561 @implementation JVBuddy (JVBuddyPrivate) 547 - (void) _buddyOnline:(NSNotification *) notification { 548 MVChatUser *user = [notification object]; 549 BOOL cameOnline = ( ! [_users count] ? YES : NO ); 562 - (void) _addUser:(MVChatUser *) user { 563 if( [_users containsObject:user] ) 564 return; 565 566 BOOL cameOnline = ! [_users count]; 550 567 [_users addObject:user]; 551 568 552 if( [self status] != MVChatUserAvailableStatus && [self status] != MVChatUserAwayStatus ) [self setActiveUser:user]; 553 if( cameOnline ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyCameOnlineNotification object:self userInfo:nil]; 554 } 555 556 - (void) _buddyOffline:(NSNotification *) notification { 557 MVChatUser *user = [notification object]; 569 if( [self status] != MVChatUserAvailableStatus && [self status] != MVChatUserAwayStatus ) 570 [self setActiveUser:user]; 571 572 if( cameOnline ) 573 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyCameOnlineNotification object:self userInfo:nil]; 574 } 575 576 - (void) _removeUser:(MVChatUser *) user { 577 if( ! [_users containsObject:user] ) 578 return; 579 558 580 [_users removeObject:user]; 559 581 … … 561 583 [self setActiveUser:[_users anyObject]]; 562 584 563 if( ! [_users count] ) [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyWentOfflineNotification object:self userInfo:nil]; 585 if( ! [_users count] ) 586 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyWentOfflineNotification object:self userInfo:nil]; 564 587 } 565 588 … … 572 595 - (void) _buddyStatusChanged:(NSNotification *) notification { 573 596 MVChatUser *user = [notification object]; 574 NSNotification *note = [NSNotification notificationWithName:JVBuddyUserStatusChangedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 575 [[NSNotificationQueue defaultQueue] enqueueNotification:note postingStyle:NSPostASAP coalesceMask:( NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender ) forModes:nil]; 597 598 switch( [user status] ) { 599 case MVChatUserAvailableStatus: 600 case MVChatUserAwayStatus: 601 [self _addUser:user]; 602 break; 603 case MVChatUserOfflineStatus: 604 case MVChatUserDetachedStatus: 605 [self _removeUser:user]; 606 default: break; 607 } 608 609 [[NSNotificationCenter defaultCenter] postNotificationName:JVBuddyUserStatusChangedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 576 610 } 577 611 … … 600 634 MVChatUser *user = [[notification userInfo] objectForKey:@"user"]; 601 635 602 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOnline: ) name:MVChatConnectionWatchedUserOnlineNotification object:user]; 603 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyOffline: ) name:MVChatConnectionWatchedUserOfflineNotification object:user]; 636 if( [user status] == MVChatUserAvailableStatus || [user status] == MVChatUserAwayStatus ) 637 [self _addUser:user]; 638 604 639 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyIdleUpdate: ) name:MVChatUserIdleTimeUpdatedNotification object:user]; 605 640 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _buddyStatusChanged: ) name:MVChatUserStatusChangedNotification object:user]; 641 } 642 643 - (void) _ruleUserRemoved:(NSNotification *) notification { 644 MVChatUser *user = [[notification userInfo] objectForKey:@"user"]; 645 646 [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserIdleTimeUpdatedNotification object:user]; 647 [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserStatusChangedNotification object:user]; 648 649 [self _removeUser:user]; 606 650 } 607 651 @end
