#import "JVChatRoomPanel.h" #import "JVChatRoomMember.h" #import "JVChatController.h" #import "MVBuddyListController.h" #import "MVFileTransferController.h" #import "JVBuddy.h" #import "JVChatUserInspector.h" #import "MVConnectionsController.h" #import "MVChatUserAdditions.h" @interface JVChatRoomMember (JVChatMemberPrivate) - (NSString *) _selfStoredNickname; - (NSString *) _selfCompositeName; - (void) _detach; @end #pragma mark - @implementation JVChatRoomMember + (void) initialize { [super initialize]; static BOOL tooLate = NO; if( ! tooLate ) { [[NSScriptCoercionHandler sharedCoercionHandler] registerCoercer:[self class] selector:@selector( coerceChatRoomMember:toString: ) toConvertFromClass:[JVChatRoomMember class] toClass:[NSString class]]; tooLate = YES; } } + (id) coerceChatRoomMember:(id) value toString:(Class) class { return [value nickname]; } #pragma mark - - (id) initWithRoom:(JVChatRoomPanel *) room andUser:(MVChatUser *) user { if( ( self = [self init] ) ) { _room = room; // prevent circular retain _user = [user retain]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatUserInformationUpdatedNotification object:user]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatUserStatusChangedNotification object:user]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatUserAwayStatusMessageChangedNotification object:user]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatUserIdleTimeUpdatedNotification object:user]; } return self; } - (id) initLocalMemberWithRoom:(JVChatRoomPanel *) room { return [self initWithRoom:room andUser:[[room connection] localUser]]; } - (void) dealloc { [self _detach]; [_user release]; _room = nil; _user = nil; [super dealloc]; } #pragma mark - #pragma mark Comparisons - (NSComparisonResult) compare:(JVChatRoomMember *) member { return [[self title] caseInsensitiveCompare:[member title]]; } - (NSComparisonResult) compareUsingStatus:(JVChatRoomMember *) member { NSComparisonResult retVal = NSOrderedSame; NSUInteger myStatus = 0; if( [self serverOperator] ) myStatus = 6; else if( [self roomFounder] ) myStatus = 5; else if( [self roomAdministrator] ) myStatus = 4; else if( [self operator] ) myStatus = 3; else if( [self halfOperator] ) myStatus = 2; else if( [self voice] ) myStatus = 1; NSUInteger yourStatus = 0; if( [member serverOperator] ) yourStatus = 6; else if( [member roomFounder] ) yourStatus = 5; else if( [member roomAdministrator] ) yourStatus = 4; else if( [member operator] ) yourStatus = 3; else if( [member halfOperator] ) yourStatus = 2; else if( [member voice] ) yourStatus = 1; if( myStatus > yourStatus ) { retVal = NSOrderedAscending; } else if( yourStatus > myStatus ) { retVal = NSOrderedDescending; } else { retVal = [[self title] caseInsensitiveCompare:[member title]]; } return retVal; } - (NSComparisonResult) compareUsingBuddyStatus:(JVChatRoomMember *) member { NSComparisonResult retVal; JVBuddy *buddy1 = [self buddy]; JVBuddy *buddy2 = [member buddy]; if( ( buddy1 && buddy2) || ( ! buddy1 && ! buddy2) ) { if( buddy1 && buddy2 ) { // if both are buddies, sort by availability retVal = [buddy1 availabilityCompare:buddy2]; } else { retVal = [[self title] caseInsensitiveCompare:[member title]]; // maybe an alpha sort here } } else if( buddy1 ) { // we have a buddy but since the first test failed, member does not retVal = NSOrderedAscending; } else { // member is a buddy retVal = NSOrderedDescending; } return retVal; } #pragma mark - #pragma mark Associations - (JVChatRoomPanel *) room { return _room; } - (MVChatConnection *) connection { return [_user connection]; } - (MVChatUser *) user { return _user; } - (JVBuddy *) buddy { return [[MVBuddyListController sharedBuddyList] buddyForUser:_user]; } #pragma mark - #pragma mark User Info - (NSString *) displayName { return [_user displayName]; } - (NSString *) nickname { return [_user nickname]; } - (NSString *) realName { return [_user realName]; } - (NSString *) username { return [_user username]; } - (NSString *) address { return [_user address]; } - (NSString *) hostmask { if( ! [[_user username] length] || ! [[_user address] length] ) return nil; return [NSString stringWithFormat:@"%@@%@", [_user username], [_user address]]; } #pragma mark - #pragma mark User Status - (BOOL) quieted { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberQuietedMode ); } - (BOOL) voice { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberVoicedMode ); } - (BOOL) operator { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberOperatorMode ); } - (BOOL) halfOperator { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberHalfOperatorMode ); } - (BOOL) roomAdministrator { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberAdministratorMode ); } - (BOOL) roomFounder { return ( [[_room target] modesForMemberUser:_user] & MVChatRoomMemberFounderMode ); } - (BOOL) serverOperator { return [_user isServerOperator]; } - (BOOL) isLocalUser { return [_user isLocalUser]; } - (NSString *) description { return [self nickname]; } - (NSString *) xmlDescription { return [self xmlDescriptionWithTagName:@"member"]; } - (NSString *) xmlDescriptionWithTagName:(NSString *) tag { NSParameterAssert( [tag length] != 0 ); // Full format will look like: // ... NSMutableString *ret = [NSMutableString string]; [ret appendFormat:@"<%@", tag]; if( [self isLocalUser] ) [ret appendString:@" self=\"yes\""]; if( ! [[self displayName] isEqualToString:[self nickname]] ) [ret appendFormat:@" nickname=\"%@\"", [[self nickname] stringByEncodingXMLSpecialCharactersAsEntities]]; id hostmask = [self hostmask]; if( hostmask ) [ret appendFormat:@" hostmask=\"%@\"", [hostmask stringByEncodingXMLSpecialCharactersAsEntities]]; id uniqueId = [_user uniqueIdentifier]; if( ! [uniqueId isEqual:[self nickname]] ) { if( [uniqueId isKindOfClass:[NSData class]] ) uniqueId = [uniqueId base64Encoding]; else if( [uniqueId isKindOfClass:[NSString class]] ) uniqueId = [uniqueId stringByEncodingXMLSpecialCharactersAsEntities]; [ret appendFormat:@" identifier=\"%@\"", uniqueId]; } NSString *class = nil; if( [self serverOperator] ) class = @"server operator"; else if( [self roomFounder] ) class = @"founder"; else if( [self roomAdministrator] ) class = @"administrator"; else if( [self operator] ) class = @"operator"; else if( [self halfOperator] ) class = @"half operator"; else if( [self voice] ) class = @"voice"; if( class ) [ret appendFormat:@" class=\"%@\"", class]; if( [self buddy] && ! [self isLocalUser] ) [ret appendFormat:@" buddy=\"%@\"", [[[self buddy] uniqueIdentifier] stringByEncodingXMLSpecialCharactersAsEntities]]; [ret appendFormat:@">%@", [[self displayName] stringByEncodingXMLSpecialCharactersAsEntities], tag]; [ret stripIllegalXMLCharacters]; return [NSString stringWithString:ret]; } #pragma mark - #pragma mark List Item Protocol Support - (id ) parent { return _room; } - (NSImage *) icon { NSUInteger modes = [[_room target] modesForMemberUser:_user]; NSString *iconName = @"person"; if( [_user isServerOperator] ) iconName = @"admin"; else if( modes & MVChatRoomMemberFounderMode ) iconName = @"founder"; else if( modes & MVChatRoomMemberAdministratorMode ) iconName = @"super-op"; else if( modes & MVChatRoomMemberOperatorMode ) iconName = @"op"; else if( modes & MVChatRoomMemberHalfOperatorMode ) iconName = @"half-op"; else if( modes & MVChatRoomMemberVoicedMode ) iconName = @"voice"; return [NSImage imageNamed:iconName]; } - (NSImage *) statusImage { if( [self buddy] ) { switch( [_user status] ) { case MVChatUserAwayStatus: return [NSImage imageNamed:@"statusAway"]; case MVChatUserAvailableStatus: if( [_user idleTime] >= 600. ) return [NSImage imageNamed:@"statusIdle"]; return [NSImage imageNamed:@"statusAvailable"]; default: return nil; } } return nil; } - (NSString *) title { if( [self isLocalUser] ) { JVBuddyName nameStyle = [[NSUserDefaults standardUserDefaults] integerForKey:@"JVChatSelfNameStyle"]; if( nameStyle == JVBuddyFullName ) return [self _selfCompositeName]; if( nameStyle == JVBuddyGivenNickname ) return [self _selfStoredNickname]; return [self nickname]; } JVBuddy *buddy = [self buddy]; if( buddy ) { if( [JVBuddy preferredName] == JVBuddyFullName && [[buddy compositeName] length] ) return [buddy compositeName]; if( [JVBuddy preferredName] == JVBuddyGivenNickname && [[buddy givenNickname] length] ) return [buddy givenNickname]; } return [self nickname]; } - (NSString *) information { return nil; } - (NSString *) toolTip { if( ! [[self address] length] || ! [[self username] length] ) { if( [[self realName] length] ) return [NSString stringWithFormat:@"%@ (%@)", [self nickname], [self realName]]; return [self nickname]; } if( [[self realName] length] ) return [NSString stringWithFormat:@"%@ (%@)\n%@@%@", [self nickname], [self realName], [self username], [self address]]; return [NSString stringWithFormat:@"%@\n%@@%@", [self nickname], [self username], [self address]]; } - (BOOL) isEnabled { return [_room isEnabled] && ! ( [_user status] == MVChatUserAwayStatus || [_user idleTime] > 600. ); } #pragma mark - - (BOOL) acceptsDraggedFileOfType:(NSString *) type { return YES; } - (void) handleDraggedFile:(NSString *) path { BOOL passive = [[NSUserDefaults standardUserDefaults] boolForKey:@"JVSendFilesPassively"]; [[MVFileTransferController defaultController] addFileTransfer:[_user sendFile:path passively:passive]]; } #pragma mark - - (IBAction) getInfo:(id) sender { [[JVInspectorController inspectorOfObject:self] show:sender]; } - (NSMenu *) menu { NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; NSMenuItem *item = nil; for( item in [_user standardMenuItems] ) [menu addItem:item]; NSUInteger localUserModes = ( [[self connection] localUser] ? [(MVChatRoom *)[_room target] modesForMemberUser:[[self connection] localUser]] : 0 ); BOOL localUserIsOperator = ( localUserModes & MVChatRoomMemberOperatorMode ); BOOL localUserIsHalfOperator = ( localUserModes & MVChatRoomMemberHalfOperatorMode ); BOOL localUserIsAdministrator = ( localUserModes & MVChatRoomMemberAdministratorMode ); BOOL localUserIsFounder = ( localUserModes & MVChatRoomMemberFounderMode ); // BOOL localUserIsServerOperator = [[[self connection] localUser] isServerOperator]; if( localUserIsHalfOperator || localUserIsOperator || localUserIsAdministrator || localUserIsFounder ) { [menu addItem:[NSMenuItem separatorItem]]; item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Kick From Room", "kick from room contextual menu - admin only" ) action:@selector( kick: ) keyEquivalent:@""] autorelease]; [item setTarget:self]; [menu addItem:item]; item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( [NSString stringWithUTF8String:"Kick From Room..."], "kick from room (customized) contextual menu - admin only" ) action:@selector( customKick: ) keyEquivalent:@""] autorelease]; [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; [item setAlternate:YES]; [item setTarget:self]; [menu addItem:item]; if( [self address] ) { item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Ban From Room", "ban from room contextual menu - admin only" ) action:@selector( ban: ) keyEquivalent:@""] autorelease]; [item setTarget:self]; [menu addItem:item]; item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( [NSString stringWithUTF8String:"Ban From Room..."], "ban from room (customized) contextual menu - admin only" ) action:@selector( customBan: ) keyEquivalent:@""] autorelease]; [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; [item setAlternate:YES]; [item setTarget:self]; [menu addItem:item]; item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Kick & Ban From Room", "kickban from room contextual menu - admin only" ) action:@selector( kickban: ) keyEquivalent:@""] autorelease]; [item setTarget:self]; [menu addItem:item]; item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( [NSString stringWithUTF8String:"Kick & Ban From Room..."], "kickban from room (customized) contextual menu - admin only" ) action:@selector( customKickban: ) keyEquivalent:@""] autorelease]; [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; [item setAlternate:YES]; [item setTarget:self]; [menu addItem:item]; } } [menu addItem:[NSMenuItem separatorItem]]; NSSet *features = [[self connection] supportedFeatures]; if( ( localUserIsFounder ) && ( [features containsObject:MVChatRoomMemberFounderFeature] ) ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Founder", "founder contextual menu - admin only") action:@selector( toggleFounderStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } if( ( ( localUserIsAdministrator || localUserIsFounder ) && ( (localUserIsAdministrator && ! [self roomFounder]) || localUserIsFounder ) ) && ( [features containsObject:MVChatRoomMemberAdministratorFeature] ) ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Administrator", "administrator contextual menu - admin only") action:@selector( toggleAdministratorStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } if( ( localUserIsOperator || localUserIsAdministrator || localUserIsFounder ) && ( (localUserIsOperator && ! ([self roomAdministrator] || [self roomFounder])) || (localUserIsAdministrator && ! [self roomFounder]) || localUserIsFounder ) ) { if( [features containsObject:MVChatRoomMemberOperatorFeature] ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Operator", "operator contextual menu - admin only") action:@selector( toggleOperatorStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } if( [features containsObject:MVChatRoomMemberHalfOperatorFeature] ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Half Operator", "half operator contextual menu - admin only") action:@selector( toggleHalfOperatorStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } } if( localUserIsHalfOperator || localUserIsOperator || localUserIsAdministrator || localUserIsFounder ) { if( [features containsObject:MVChatRoomMemberVoicedFeature] && ( (localUserIsHalfOperator && ! ([self operator] || [self roomAdministrator] || [self roomFounder]) ) || (localUserIsOperator && ! ([self roomAdministrator] || [self roomFounder])) || (localUserIsAdministrator && ! [self roomFounder]) || localUserIsFounder ) ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Voice", "voice contextual menu - admin only") action:@selector( toggleVoiceStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } if( [features containsObject:MVChatRoomMemberQuietedFeature] ) { item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Quieted", "quieted contextual menu - admin only") action:@selector( toggleQuietedStatus: ) keyEquivalent:@""]; [item setTarget:self]; [menu addItem:item]; [item release]; } } if( [[[menu itemArray] lastObject] isSeparatorItem] ) [menu removeItem:[[menu itemArray] lastObject]]; return menu; } - (BOOL) validateMenuItem:(NSMenuItem *) menuItem { if( ! [[self connection] isConnected] ) return NO; if( [menuItem action] == @selector( toggleVoiceStatus: ) ) { if( [self voice] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } else if( [menuItem action] == @selector( toggleQuietedStatus: ) ) { if( [self quieted] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } else if( [menuItem action] == @selector( toggleOperatorStatus: ) ) { if( [self operator] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } else if( [menuItem action] == @selector( toggleHalfOperatorStatus: ) ) { if( [self halfOperator] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } else if( [menuItem action] == @selector( toggleAdministratorStatus: ) ) { if( [self roomAdministrator] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } else if( [menuItem action] == @selector( toggleFounderStatus: ) ) { if( [self roomFounder] ) { [menuItem setState:NSOnState]; } else { [menuItem setState:NSOffState]; } } return YES; } #pragma mark - #pragma mark Scripting Support - (NSNumber *) uniqueIdentifier { return [NSNumber numberWithUnsignedLong:(intptr_t)self]; } - (NSArray *) children { return nil; } #pragma mark - #pragma mark GUI Actions - (IBAction) doubleClicked:(id) sender { [_user startChat:sender]; } - (IBAction) startChat:(id) sender { [_user startChat:sender]; } - (IBAction) sendFile:(id) sender { [_user sendFile:sender]; } - (IBAction) addBuddy:(id) sender { [_user addBuddy:sender]; } - (IBAction) toggleIgnore:(id) sender { [_user toggleIgnore:sender]; } #pragma mark - #pragma mark Operator Actions - (IBAction) toggleFounderStatus:(id) sender { if( [self roomFounder] ) [[_room target] removeMode:MVChatRoomMemberFounderMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberFounderMode forMemberUser:_user]; } - (IBAction) toggleAdministratorStatus:(id) sender { if( [self roomAdministrator] ) [[_room target] removeMode:MVChatRoomMemberAdministratorMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberAdministratorMode forMemberUser:_user]; } - (IBAction) toggleOperatorStatus:(id) sender { if( [self operator] ) [[_room target] removeMode:MVChatRoomMemberOperatorMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberOperatorMode forMemberUser:_user]; } - (IBAction) toggleHalfOperatorStatus:(id) sender { if( [self halfOperator] ) [[_room target] removeMode:MVChatRoomMemberHalfOperatorMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberHalfOperatorMode forMemberUser:_user]; } - (IBAction) toggleVoiceStatus:(id) sender { if( [self voice] ) [[_room target] removeMode:MVChatRoomMemberVoicedMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberVoicedMode forMemberUser:_user]; } - (IBAction) toggleQuietedStatus:(id) sender { if( [self quieted] ) [[_room target] removeMode:MVChatRoomMemberQuietedMode forMemberUser:_user]; else [[_room target] setMode:MVChatRoomMemberQuietedMode forMemberUser:_user]; } #pragma mark - - (IBAction) kick:(id) sender { [[_room target] kickOutMemberUser:_user forReason:nil]; } - (IBAction) ban:(id) sender { MVChatUser *user = [MVChatUser wildcardUserWithNicknameMask:nil andHostMask:[NSString stringWithFormat:@"*@%@", [self address]]]; [[_room target] addBanForUser:user]; } - (IBAction) customKick:(id) sender { if( ! _nibLoaded ) _nibLoaded = [NSBundle loadNibNamed:@"TSCustomBan" owner:self]; if( ! _nibLoaded ) { NSLog( @"Can't load TSCustomBan.nib" ); return; } [banTitle setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Kick %@ from the %@ room.", "kick user from room" ), [self title], [_room title]]]; [firstTitle setStringValue:NSLocalizedString( @"With reason:", "kick reason label" )]; [firstField setStringValue:@""]; [banWindow makeFirstResponder:firstField]; [secondTitle setHidden:YES]; [secondField setHidden:YES]; NSRect frame = [banWindow frame]; frame.size.height = ( frame.size.height - [firstField frame].origin.y ) + 60.; [banWindow setFrame:frame display:YES]; [banButton setAction:@selector( closeKickSheet: )]; [banButton setTitle:NSLocalizedString( @"Kick User", "kick user button" )]; [banButton setTarget:self]; [[NSApplication sharedApplication] beginSheet:banWindow modalForWindow:[[_room view] window] modalDelegate:nil didEndSelector:nil contextInfo:nil]; } - (IBAction) customBan:(id) sender { if( ! _nibLoaded ) _nibLoaded = [NSBundle loadNibNamed:@"TSCustomBan" owner:self]; if( ! _nibLoaded ) { NSLog( @"Can't load TSCustomBan.nib" ); return; } [banTitle setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Ban %@ from the %@ room.", "ban user from room label" ), [self title], [_room title]]]; [firstTitle setStringValue:NSLocalizedString( @"With hostmask:", "ban hostmask label")]; if( [self username] && [self address] ) [firstField setStringValue:[NSString stringWithFormat:@"%@!%@@%@", [self nickname], [self username], [self address]]]; else [firstField setStringValue:@""]; [banWindow makeFirstResponder:firstField]; [secondTitle setHidden:YES]; [secondField setHidden:YES]; NSRect frame = [banWindow frame]; frame.size.height = ( frame.size.height - [firstField frame].origin.y ) + 60.; [banWindow setFrame:frame display:YES]; [banButton setAction:@selector( closeBanSheet: )]; [banButton setTitle:NSLocalizedString( @"Ban User", "ban user button" )]; [banButton setTarget:self]; [[NSApplication sharedApplication] beginSheet:banWindow modalForWindow:[[_room view] window] modalDelegate:nil didEndSelector:nil contextInfo:nil]; } - (IBAction) kickban:(id) sender { [self ban:nil]; [self kick:nil]; } - (IBAction) customKickban:(id) sender { if( ! _nibLoaded ) _nibLoaded = [NSBundle loadNibNamed:@"TSCustomBan" owner:self]; if( ! _nibLoaded ) { NSLog(@"Can't load TSCustomBan.nib"); return; } [banTitle setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Kick and ban %@ from the %@ room.", "kickban user from room" ), [self title], [_room title]]]; [banTitle sizeToFit]; [firstTitle setStringValue:NSLocalizedString( @"With hostmask:", "ban hostmask" )]; [secondTitle setStringValue:NSLocalizedString( @"And reason:", "kick reason (secondary)" )]; if( [self username] && [self address] ) [firstField setStringValue:[NSString stringWithFormat:@"%@!%@@%@", [self nickname], [self username], [self address]]]; else [firstField setStringValue:@""]; [secondField setStringValue:@""]; [banWindow makeFirstResponder:firstField]; [secondTitle setHidden:NO]; [secondField setHidden:NO]; NSRect frame = [banWindow frame]; frame.size.height = ( frame.size.height - [secondField frame].origin.y ) + 60; [banWindow setFrame:frame display:YES]; [banButton setAction:@selector( closeKickbanSheet: )]; [banButton setTitle:NSLocalizedString( @"Kick & Ban User", "kick and ban user button" )]; [banButton setTarget:self]; [[NSApplication sharedApplication] beginSheet:banWindow modalForWindow:[[_room view] window] modalDelegate:nil didEndSelector:nil contextInfo:nil]; } - (IBAction) closeKickSheet:(id) sender { [[NSApplication sharedApplication] endSheet:banWindow]; [banWindow orderOut:self]; NSAttributedString *reason = [[[NSAttributedString alloc] initWithString:[firstField stringValue]] autorelease]; [[_room target] kickOutMemberUser:_user forReason:reason]; } - (IBAction) closeBanSheet:(id) sender { [[NSApplication sharedApplication] endSheet:banWindow]; [banWindow orderOut:self]; MVChatUser *user = [MVChatUser wildcardUserFromString:[firstField stringValue]]; [[_room target] addBanForUser:user]; } - (IBAction) closeKickbanSheet:(id) sender { [[NSApplication sharedApplication] endSheet:banWindow]; [banWindow orderOut:self]; MVChatUser *user = [MVChatUser wildcardUserFromString:[firstField stringValue]]; [[_room target] addBanForUser:user]; NSAttributedString *reason = [[[NSAttributedString alloc] initWithString:[secondField stringValue]] autorelease]; [[_room target] kickOutMemberUser:_user forReason:reason]; } - (IBAction) cancelSheet:(id) sender { [[NSApplication sharedApplication] endSheet:banWindow]; [banWindow orderOut:self]; } #pragma mark - - (id) valueForUndefinedKey:(NSString *) key { if( [NSScriptCommand currentCommand] ) { [[NSScriptCommand currentCommand] setScriptErrorNumber:1000]; [[NSScriptCommand currentCommand] setScriptErrorString:[NSString stringWithFormat:@"The member id %@ of chat room panel id %@ doesn't have the \"%@\" property.", [self uniqueIdentifier], [_room uniqueIdentifier], key]]; return nil; } return [super valueForUndefinedKey:key]; } - (void) setValue:(id) value forUndefinedKey:(NSString *) key { if( [NSScriptCommand currentCommand] ) { [[NSScriptCommand currentCommand] setScriptErrorNumber:1000]; [[NSScriptCommand currentCommand] setScriptErrorString:[NSString stringWithFormat:@"The \"%@\" property of member id %@ of chat room panel id %@ is read only.", key, [self uniqueIdentifier], [_room uniqueIdentifier]]]; return; } [super setValue:value forUndefinedKey:key]; } @end #pragma mark - @implementation JVChatRoomMember (JVChatMemberPrivate) - (void) _detach { [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserInformationUpdatedNotification object:_user]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserStatusChangedNotification object:_user]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserAwayStatusMessageChangedNotification object:_user]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MVChatUserIdleTimeUpdatedNotification object:_user]; _room = nil; } - (void) _refreshIcon:(NSNotification *) notification { [[_room windowController] reloadListItem:self andChildren:NO]; } - (NSString *) _selfCompositeName { ABPerson *_person = [[ABAddressBook sharedAddressBook] me]; NSString *firstName = [_person valueForProperty:kABFirstNameProperty]; NSString *lastName = [_person valueForProperty:kABLastNameProperty]; if( ! firstName && lastName ) return lastName; else if( firstName && ! lastName ) return firstName; else if( firstName && lastName ) { return [NSString stringWithFormat:@"%@ %@", firstName, lastName]; } firstName = [_person valueForProperty:kABNicknameProperty]; if( firstName ) return firstName; return [[self connection] nickname]; } - (NSString *) _selfStoredNickname { NSString *nickname = [[[ABAddressBook sharedAddressBook] me] valueForProperty:kABNicknameProperty]; if( nickname ) return nickname; return [[self connection] nickname]; } @end