Update the icon in the personal preferences if it's changed elsewhere (the contact...
[adiumx.git] / Source / AIStatusChangedMessagesPlugin.m
blob81a9c67c15d4c188ed87dd95f4228984bb811634
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import "AIStatusChangedMessagesPlugin.h"
18 #import <Adium/AIChatControllerProtocol.h>
19 #import <Adium/AIContentControllerProtocol.h>
20 #import <Adium/AIContactAlertsControllerProtocol.h>
21 #import <Adium/AIListContact.h>
22 #import <Adium/AIChat.h>
23 #import <Adium/AIContentStatus.h>
25 @interface AIStatusChangedMessagesPlugin (PRIVATE)
26 - (void)statusMessage:(NSString *)message forContact:(AIListContact *)contact 
27                          withType:(NSString *)type
28  phraseWithoutSubject:(NSString *)statusPhrase
29                 loggedMessage:(NSAttributedString *)loggedMessage
30                           inChats:(NSSet *)inChats;
31 @end
33 /*!
34  * @class AIStatusChangedMessagesPlugin
35  * @brief Generate <tt>AIContentStatus</tt> messages in open chats in response to contact status changes
36  */
37 @implementation AIStatusChangedMessagesPlugin
39 static  NSDictionary    *statusTypeDict = nil;
41 /*!
42  * @brief Install
43  */
44 - (void)installPlugin
46         statusTypeDict = [[NSDictionary dictionaryWithObjectsAndKeys:
47                 @"away",CONTACT_STATUS_AWAY_YES,
48                 @"return_away",CONTACT_STATUS_AWAY_NO,
49                 @"online",CONTACT_STATUS_ONLINE_YES,
50                 @"offline",CONTACT_STATUS_ONLINE_NO,
51                 @"idle",CONTACT_STATUS_IDLE_YES,
52                 @"return_idle",CONTACT_STATUS_IDLE_NO,
53                 @"away_message",CONTACT_STATUS_MESSAGE,
54                 nil] retain];
55         
56         previousStatusChangedMessages = [[NSMutableDictionary alloc] init];
57         
58     //Observe contact status changes
59     [[adium notificationCenter] addObserver:self selector:@selector(contactStatusChanged:) name:CONTACT_STATUS_ONLINE_YES object:nil];
60     [[adium notificationCenter] addObserver:self selector:@selector(contactStatusChanged:) name:CONTACT_STATUS_ONLINE_NO object:nil];
61     [[adium notificationCenter] addObserver:self selector:@selector(contactStatusChanged:) name:CONTACT_STATUS_IDLE_YES object:nil];
62     [[adium notificationCenter] addObserver:self selector:@selector(contactStatusChanged:) name:CONTACT_STATUS_IDLE_NO object:nil];
64         [[adium notificationCenter] addObserver:self selector:@selector(contactAwayChanged:) name:CONTACT_STATUS_AWAY_YES object:nil];
65     [[adium notificationCenter] addObserver:self selector:@selector(contactAwayChanged:) name:CONTACT_STATUS_AWAY_NO object:nil];
66     [[adium notificationCenter] addObserver:self selector:@selector(contact_statusMessage:) name:CONTACT_STATUS_MESSAGE object:nil];
67         
68         [[adium notificationCenter] addObserver:self
69                                                                    selector:@selector(chatWillClose:)
70                                                                            name:Chat_WillClose
71                                                                          object:nil];   
74 - (void)uninstallPlugin
76         [previousStatusChangedMessages release];
79 /*!
80  * @brief Notification a changed status message
81  *
82  * @param notification <tt>NSNotification</tt> whose object is the AIListContact
83  */
84 - (void)contact_statusMessage:(NSNotification *)notification{
85         NSSet                   *allChats;
86         AIListContact   *contact = [notification object];
87         
88         allChats = [[adium chatController] allChatsWithContact:contact];
89         AILog(@"Status message for %@ changed (%@)",contact,allChats);
90         if ([allChats count]) { 
91                 if ([contact statusType] != AIAvailableStatusType) {
92                         NSAttributedString *statusMessage = [contact statusMessage];
93                         NSString                        *statusMessageString = [statusMessage string];
94                         NSString                        *statusType = [statusTypeDict objectForKey:CONTACT_STATUS_MESSAGE];
95                         
96                         if (statusMessage && [statusMessage length] != 0) {
97                                 [self statusMessage:[NSString stringWithFormat:AILocalizedString(@"Away Message: %@",nil),statusMessageString] 
98                                                  forContact:contact
99                                                    withType:statusType
100                            phraseWithoutSubject:statusMessageString
101                                           loggedMessage:statusMessage
102                                                         inChats:allChats];
103                         }
104                 }
105         }
109  * @brief Contact status changed notification
111  * @param notification <tt>NSNotification</tt> whose object is the AIListContact and whose name is the eventID
112  */
113 - (void)contactStatusChanged:(NSNotification *)notification{
114         NSSet                   *allChats;
115         AIListContact   *contact = [notification object];
116         
117         allChats = [[adium chatController] allChatsWithContact:contact];
118         if ([allChats count]) {
119                 NSString                *description, *phraseWithoutSubject;
120                 NSString                *name = [notification name];
121                 NSDictionary    *userInfo = [notification userInfo];
122                 
123                 description = [[adium contactAlertsController] naturalLanguageDescriptionForEventID:name
124                                                                                                                                                                  listObject:contact
125                                                                                                                                                                    userInfo:userInfo
126                                                                                                                                                          includeSubject:YES];
127                 phraseWithoutSubject = [[adium contactAlertsController] naturalLanguageDescriptionForEventID:name
128                                                                                                                                                                                   listObject:contact
129                                                                                                                                                                                         userInfo:userInfo
130                                                                                                                                                                           includeSubject:NO];           
131                 [self statusMessage:description
132                                  forContact:contact
133                                    withType:[statusTypeDict objectForKey:name]
134            phraseWithoutSubject:phraseWithoutSubject
135                           loggedMessage:nil
136                                         inChats:allChats];
137         }
141  * @brief Special handling for away changes
143  * We only display the "Went away" message if a status message for the away hasn't already been printed
144  */
145 - (void)contactAwayChanged:(NSNotification *)notification
147         NSDictionary    *userInfo = [notification userInfo];
148         
149         if (![[userInfo objectForKey:@"Already Posted StatusMessage"] boolValue]) {
150                 [self contactStatusChanged:notification];
151         }
155  * @brief Post a status message on all active chats for this object
156  */
157 - (void)statusMessage:(NSString *)message forContact:(AIListContact *)contact 
158                          withType:(NSString *)type
159  phraseWithoutSubject:(NSString *)statusPhrase
160                 loggedMessage:(NSAttributedString *)loggedMessage
161                           inChats:(NSSet *)inChats
163     NSEnumerator                *enumerator;
164     AIChat                              *chat;
165         NSAttributedString      *attributedMessage = [[[NSAttributedString alloc] initWithString:message
166                                                                                                                                                           attributes:[[adium contentController] defaultFormattingAttributes]] autorelease];
168         enumerator = [inChats objectEnumerator];
169         while ((chat = [enumerator nextObject])) {
170                 //Don't do anything if the message is the same as the last message displayed for this chat
171                 if ([[previousStatusChangedMessages objectForKey:[chat uniqueChatID]] isEqualToString:message])
172                         continue;
174                 AIContentStatus *content;
175                 
176                 //Create our content object
177                 content = [AIContentStatus statusInChat:chat
178                                                                          withSource:contact
179                                                                         destination:[chat account]
180                                                                                    date:[NSDate date]
181                                                                                 message:attributedMessage
182                                                                            withType:type];
183                 
184                 if (statusPhrase) {
185                         NSDictionary    *userInfo = [NSDictionary dictionaryWithObject:statusPhrase
186                                                                                                                                         forKey:@"Status Phrase"];
187                         [content setUserInfo:userInfo];
188                 }
189                 
190                 if (loggedMessage) {
191                         [content setLoggedMessage:loggedMessage];
192                 }
194                 //Add the object
195                 [[adium contentController] receiveContentObject:content];
196                 
197                 //Keep track of this message for this chat so we don't display it again sequentially
198                 [previousStatusChangedMessages setObject:message
199                                                                                   forKey:[chat uniqueChatID]];
200         }
203 - (void)chatWillClose:(NSNotification *)inNotification
205         AIChat *chat = [inNotification object];
206         [previousStatusChangedMessages removeObjectForKey:[chat uniqueChatID]];
209 @end