Adium

Changeset 15210

Show
Ignore:
Timestamp:
02/12/2006 01:33:17 PM (3 years ago)
Author:
evands
Message:

Patch from Kiel Gillard which implements a "blocked" status icon. There is a default blocked icon which will be used if the status icon set does not supply one, which it can do with a "Blocked" key. Fixes #344. Good work! :)

The patch also improves the the blocking API a bit, allowing contacts to block themselves.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Frameworks/Adium Framework/AIListContact.h

    r14780 r15210  
    4646- (void)setSignonDate:(NSDate *)signonDate notify:(NotifyTiming)notify; 
    4747- (NSDate *)signonDate; 
     48- (void)setIsBlocked:(BOOL)yesOrNo updateList:(BOOL)addToPrivacyLists; 
    4849 
    4950- (void)setIdle:(BOOL)isIdle sinceDate:(NSDate *)idleSinceDate notify:(NotifyTiming)notify; 
  • trunk/Frameworks/Adium Framework/AIListContact.m

    r14912 r15210  
    468468} 
    469469 
     470/*! 
     471 * @brief Is this contact blocked? 
     472 * 
     473 * @result A boolean indicating if the contact is blocked or not 
     474 */ 
     475- (BOOL)isBlocked 
     476{ 
     477        return [self integerStatusObjectForKey:KEY_IS_BLOCKED]; 
     478} 
     479 
     480/*! 
     481 * @brief Set if this contact is blocked 
     482 */ 
     483- (void)setIsBlocked:(BOOL)yesOrNo updateList:(BOOL)addToPrivacyLists 
     484{ 
     485        if (addToPrivacyLists) { 
     486                //caller of this method wants to block the contact 
     487                AIAccount       *contactAccount = [self account]; 
     488                 
     489                if ([contactAccount conformsToProtocol:@protocol(AIAccount_Privacy)]) { 
     490                        BOOL    result = NO; 
     491                        NSArray *privacyList = [(AIAccount <AIAccount_Privacy> *)contactAccount listObjectIDsOnPrivacyList:PRIVACY_DENY]; 
     492                         
     493                        if (yesOrNo == YES) { 
     494                                //we want to block the contact 
     495                                if (![privacyList containsObject:[self UID]]) { 
     496                                        result = [(AIAccount <AIAccount_Privacy> *)contactAccount addListObject:self toPrivacyList:PRIVACY_DENY]; 
     497                                } 
     498                        } else { 
     499                                //unblock contact 
     500                                if ([privacyList containsObject:[self UID]]) { 
     501                                        result = [(AIAccount <AIAccount_Privacy> *)contactAccount removeListObject:self fromPrivacyList:PRIVACY_DENY]; 
     502                                } 
     503                        } 
     504                         
     505                        //update status object 
     506                        if (result) { 
     507                                [self setStatusObject:(yesOrNo ? [NSNumber numberWithBool:YES] : nil) 
     508                                                           forKey:KEY_IS_BLOCKED  
     509                                                           notify:NotifyNow]; 
     510                        } 
     511                } else { 
     512                        NSLog(@"Privacy is not supported on contacts for the account: %@", contactAccount); 
     513                } 
     514        } else { 
     515                //caller of this method just wants to update the status object 
     516                [self setStatusObject:(yesOrNo ? [NSNumber numberWithBool:YES] : nil) 
     517                                           forKey:KEY_IS_BLOCKED  
     518                                           notify:NotifyNow]; 
     519        } 
     520} 
     521 
    470522#pragma mark Status 
    471523 
  • trunk/Frameworks/Adium Framework/AIListObject.h

    r15163 r15210  
    2020@class AIListObject, AIService, AIMutableOwnerArray, AIListGroup; 
    2121 
    22 #define KEY_ORDER_INDEX @"Order Index" 
     22#define KEY_ORDER_INDEX         @"Order Index" 
     23#define KEY_IS_BLOCKED          @"isBlocked" 
    2324 
    2425typedef enum { 
     
    127128- (BOOL)isStranger; 
    128129- (BOOL)isMobile; 
     130- (BOOL)isBlocked; 
    129131 
    130132- (NSString *)displayName; 
  • trunk/Frameworks/Adium Framework/AIListObject.m

    r15158 r15210  
    597597 */ 
    598598- (BOOL)isMobile 
     599{ 
     600        return NO; 
     601} 
     602 
     603/*! 
     604 * @brief Is this contact blocked? 
     605 * 
     606 * @result A boolean indicating if the object is blocked 
     607 */ 
     608- (BOOL)isBlocked 
    599609{ 
    600610        return NO; 
  • trunk/Frameworks/Adium Framework/AIMetaContact.m

    r14912 r15210  
    5454 
    5555        [super initWithUID:[objectID stringValue] service:nil]; 
    56  
     56         
    5757        containedObjects = [[NSMutableArray alloc] init]; 
    5858         
     
    186186{ 
    187187        return NO; 
     188} 
     189 
     190/*! 
     191 * @brief Are all the contacts in this meta blocked? 
     192 * 
     193 * @result Boolean flag indicating if all the listContacts are blocked 
     194 */ 
     195- (BOOL)isBlocked 
     196{ 
     197        BOOL                    allContactsBlocked = ([[self listContacts] count] ? YES : NO); 
     198        NSEnumerator    *enumerator = [[self listContacts] objectEnumerator]; 
     199        AIListContact   *currentContact = nil; 
     200         
     201        while ((currentContact = [enumerator nextObject])) { 
     202                //find any unblocked contacts 
     203                if (![currentContact isBlocked]) { 
     204                        allContactsBlocked = NO; 
     205                        break; 
     206                } 
     207        } 
     208         
     209        return allContactsBlocked; 
     210} 
     211 
     212/*! 
     213 * @brief Block each contact contained in the meta 
     214 */ 
     215- (void)setIsBlocked:(BOOL)yesOrNo updateList:(BOOL)addToPrivacyLists 
     216{ 
     217        NSEnumerator    *contactEnumerator = [[self listContacts] objectEnumerator]; 
     218        AIListContact   *currentContact = nil; 
     219         
     220        //attempt to block entire meta 
     221        while ((currentContact = [contactEnumerator nextObject])) { 
     222                [currentContact setIsBlocked:yesOrNo updateList:addToPrivacyLists]; 
     223        } 
     224         
     225        //update status object if we are completely blocked 
     226        [self setStatusObject:([self isBlocked] ? [NSNumber numberWithBool:YES] : nil) 
     227                                   forKey:KEY_IS_BLOCKED  
     228                                   notify:NotifyNow]; 
    188229} 
    189230 
  • trunk/Frameworks/Adium Framework/AIStatusIcons.m

    r14112 r15210  
    136136                        } 
    137137                } else { 
    138                         NSString        *defaultStatusName = defaultNameForStatusType(statusType); 
    139  
    140                         if (![defaultStatusName isEqualToString:statusName]) { 
    141                                 /* If the pack doesn't provide an icon for this specific status name, fall back on and then cache the default. */ 
    142                                 if ((statusIcon = [self statusIconForStatusName:defaultStatusName 
    143                                                                                                         statusType:statusType 
    144                                                                                                           iconType:iconType 
    145                                                                                                          direction:iconDirection])) { 
     138                        if ([statusName isEqualToString:@"Blocked"]) { 
     139                                //We want a blocked icon but the status set does not give us one 
     140                                statusIcon = [NSImage imageNamed:@"DefaultBlockedStatusIcon" forClass:[self class]]; 
     141                                 
     142                                if (statusIcon) { 
     143                                        if (iconDirection == AIIconFlipped) [statusIcon setFlipped:YES]; 
    146144                                        [statusIcons[iconType][iconDirection] setObject:statusIcon forKey:statusName]; 
    147                                 } 
    148  
    149                         } else { 
    150                                 if (statusType == AIInvisibleStatusType) { 
    151                                         /* If we get here with an invisible status type, fall back on AIAwayStatusType */ 
    152                                         if ((statusIcon = [self statusIconForStatusName:nil 
    153                                                                                                                 statusType:AIAwayStatusType 
    154                                                                                                                   iconType:iconType 
    155                                                                                                                  direction:iconDirection])) { 
     145                                }                                
     146                        } 
     147 
     148                        if (!statusIcon) { 
     149                                NSString        *defaultStatusName = defaultNameForStatusType(statusType); 
     150                                 
     151                                if (![defaultStatusName isEqualToString:statusName]) { 
     152                                        /* If the pack doesn't provide an icon for this specific status name, fall back on and then cache the default. */ 
     153                                        if ((statusIcon = [self statusIconForStatusName:defaultStatusName 
     154                                                                                                                 statusType:statusType 
     155                                                                                                                   iconType:iconType 
     156                                                                                                                  direction:iconDirection])) { 
    156157                                                [statusIcons[iconType][iconDirection] setObject:statusIcon forKey:statusName]; 
    157158                                        } 
    158159                                         
    159160                                } else { 
    160                                         NSString        *errorMessage; 
    161                                          
    162                                         errorMessage = [NSString stringWithFormat: 
    163                                                 AILocalizedStringFromTable(@"The active status icon pack \"%@\" installed at \"%@\" is invalid.  It is missing the required status icon \"%@\".  If you received this pack from adiumxtras.com, please contact its author. Your status icon setting will be restored to the default.", @"AdiumFramework", nil), 
    164                                                 [[statusIconBasePath lastPathComponent] stringByDeletingPathExtension], 
    165                                                 statusIconBasePath, 
    166                                                 defaultStatusName]; 
    167                                          
    168                                         NSRunCriticalAlertPanel(AILocalizedStringFromTable(@"Invalid status icon pack", @"AdiumFramework", nil),errorMessage,nil,nil,nil); 
    169                                          
    170                                         //Post a notification so someone, somewhere can fix us :) 
    171                                         [[[AIObject sharedAdiumInstance] notificationCenter] postNotificationName:AIStatusIconSetInvalidSetNotification 
    172                                                                                                                                                                            object:nil]; 
    173                                 } 
     161                                        if (statusType == AIInvisibleStatusType) { 
     162                                                /* If we get here with an invisible status type, fall back on AIAwayStatusType */ 
     163                                                if ((statusIcon = [self statusIconForStatusName:nil 
     164                                                                                                                         statusType:AIAwayStatusType 
     165                                                                                                                           iconType:iconType 
     166                                                                                                                          direction:iconDirection])) { 
     167                                                        [statusIcons[iconType][iconDirection] setObject:statusIcon forKey:statusName]; 
     168                                                } 
     169                                                 
     170                                        } else { 
     171                                                NSString        *errorMessage; 
     172                                                 
     173                                                errorMessage = [NSString stringWithFormat: 
     174                                                        AILocalizedStringFromTable(@"The active status icon pack \"%@\" installed at \"%@\" is invalid.  It is missing the required status icon \"%@\".  If you received this pack from adiumxtras.com, please contact its author. Your status icon setting will be restored to the default.", @"AdiumFramework", nil), 
     175                                                        [[statusIconBasePath lastPathComponent] stringByDeletingPathExtension], 
     176                                                        statusIconBasePath, 
     177                                                        defaultStatusName]; 
     178                                                 
     179                                                NSRunCriticalAlertPanel(AILocalizedStringFromTable(@"Invalid status icon pack", @"AdiumFramework", nil),errorMessage,nil,nil,nil); 
     180                                                 
     181                                                //Post a notification so someone, somewhere can fix us :) 
     182                                                [[[AIObject sharedAdiumInstance] notificationCenter] postNotificationName:AIStatusIconSetInvalidSetNotification 
     183                                                                                                                                                                                   object:nil]; 
     184                                } 
     185                        } 
    174186                        } 
    175187                } 
     
    263275        if ([listObject isMobile]) { 
    264276                statusName = @"Mobile"; 
    265          
     277        } else if ([listObject isBlocked]) { 
     278                statusName = @"Blocked"; 
    266279        } else { 
    267280                AIStatusSummary statusSummary = [listObject statusSummary]; 
  • trunk/Source/AITabStatusIconsPlugin.m

    r13411 r15210  
    8787           [inModifiedKeys containsObject:@"IsIdle"] || 
    8888           [inModifiedKeys containsObject:@"NotAStranger"] || 
     89           [inModifiedKeys containsObject:KEY_IS_BLOCKED] || 
    8990           [inModifiedKeys containsObject:@"IsMobile"]) { 
    9091                 
  • trunk/Source/ESBlockingPlugin.m

    r14244 r15210  
    3030- (void)_blockContact:(AIListContact *)contact unblock:(BOOL)unblock; 
    3131- (BOOL)_searchPrivacyListsForListContact:(AIListContact *)contact withDesiredResult:(BOOL)desiredResult; 
     32- (void)accountConnected:(NSNotification *)notification; 
    3233@end 
    3334 
     
    4950                                                                                                                 keyEquivalent:@""]; 
    5051    [[adium menuController] addContextualMenuItem:blockContactContextualMenuItem toLocation:Context_Contact_NegativeAction]; 
     52         
     53        //we want to know when an account connects 
     54        [[adium notificationCenter] addObserver:self 
     55                                                                   selector:@selector(accountConnected:) 
     56                                                                           name:ACCOUNT_CONNECTED 
     57                                                                         object:nil]; 
    5158} 
    5259 
    5360- (void)uninstallPlugin 
    5461{ 
     62        [[adium notificationCenter] removeObserver:self]; 
    5563        [blockContactMenuItem release]; 
    5664        [blockContactContextualMenuItem release]; 
     
    7987                if (NSRunAlertPanel([NSString stringWithFormat:format, [contact displayName]], 
    8088                                                   @"", 
    81                                                    AILocalizedString(@"OK", nil)
     89                                                   [sender title]
    8290                                                   AILocalizedString(@"Cancel", nil), 
    8391                                                   nil) == NSAlertDefaultReturn) { 
     
    191199{ 
    192200        //We want to block on all accounts with the same service class. If you want someone gone, you want 'em GONE. 
    193         NSEnumerator *enumerator = [[[adium accountController] accountsCompatibleWithService:[contact service]] objectEnumerator]; 
    194         AIAccount *account = nil; 
    195  
     201        NSEnumerator    *enumerator = [[[adium accountController] accountsCompatibleWithService:[contact service]] objectEnumerator]; 
     202        AIAccount               *account = nil; 
     203        AIListContact   *sameContact = nil; 
     204         
    196205        while ((account = [enumerator nextObject])) { 
    197                 if ([account conformsToProtocol:@protocol(AIAccount_Privacy)]) { 
    198                         AIAccount <AIAccount_Privacy> *privacyAccount = (AIAccount <AIAccount_Privacy> *)account; 
    199                         if (unblock) { 
    200                                 if ([[privacyAccount listObjectIDsOnPrivacyList:PRIVACY_DENY] containsObject:[contact UID]]) { 
    201                                         [privacyAccount removeListObject:contact fromPrivacyList:PRIVACY_DENY]; 
    202                                 } 
    203                         } else { 
    204                                 if (![[privacyAccount listObjectIDsOnPrivacyList:PRIVACY_DENY] containsObject:[contact UID]]) { 
    205                                         [privacyAccount addListObject:contact toPrivacyList:PRIVACY_DENY]; 
    206                                 } 
    207                         } 
     206                sameContact = [account contactWithUID:[contact UID]]; 
     207                 
     208                if (sameContact) { 
     209                        [sameContact setIsBlocked:!unblock updateList:YES]; 
    208210                } 
    209211        } 
     
    228230} 
    229231 
     232/*! 
     233 * @brief Inform AIListContact instances of the user's intended privacy towards the people they represent 
     234 */ 
     235- (void)accountConnected:(NSNotification *)notification 
     236{ 
     237        //NSLog(@"account connected: %@", notification); 
     238         
     239        AIAccount               *accountConnected = [notification object]; 
     240        NSEnumerator    *contactEnumerator = nil; 
     241        AIListContact   *currentContact = nil; 
     242         
     243        if ([accountConnected conformsToProtocol:@protocol(AIAccount_Privacy)]) { 
     244                 
     245                //check if each contact is on the account's deny list 
     246                contactEnumerator = [[accountConnected contacts] objectEnumerator]; 
     247                while ((currentContact = [contactEnumerator nextObject])) { 
     248                        //NSLog(@"The current contact is: %@", currentContact); 
     249                         
     250                        if ([[(AIAccount <AIAccount_Privacy> *)accountConnected listObjectIDsOnPrivacyList:PRIVACY_DENY] containsObject:[currentContact UID]]) { 
     251                                //inform the contact that they're blocked 
     252                                [currentContact setIsBlocked:YES updateList:NO]; 
     253                                //NSLog(@"** %@ is blocked **", [currentContact formattedUID]); 
     254                        } else { 
     255                                [currentContact setIsBlocked:NO updateList:NO]; 
     256                        } 
     257                } 
     258        } 
     259} 
     260 
    230261@end