5 // Created by Evan Schoenberg on 3/4/05.
6 // Copyright 2006 The Adium Team. All rights reserved.
9 #import "ESAutoAwayPlugin.h"
10 #import <Adium/AIAccountControllerProtocol.h>
11 #import <Adium/AIPreferenceControllerProtocol.h>
12 #import "AIStatusController.h"
13 #import <Adium/AIAccount.h>
14 #import <Adium/AIStatus.h>
15 #import <Adium/AIStatusGroup.h>
18 * @class ESAutoAwayPlugin
19 * @brief Provides auto-away functionality for the state system
21 * This class implements auto-away. When the user is inactive for a period of time specified by the user,
22 * all accounts which are online and available are set to a specified status state.
24 @implementation ESAutoAwayPlugin
27 * @brief Initialize the auto-away system
29 * When AIMachineIdleUpdateNotification is posted, check the time idle against the time at which to switch available
30 * accounts to a state (as specified by the user in the preferences).
34 automaticAwaySet = NO;
36 [[adium notificationCenter] addObserver:self
37 selector:@selector(machineIdleUpdate:)
38 name:AIMachineIdleUpdateNotification
40 [[adium notificationCenter] addObserver:self
41 selector:@selector(machineIsActive:)
42 name:AIMachineIsActiveNotification
45 //Observe preference changes for updating when and how we should automatically change our state
46 [[adium preferenceController] registerPreferenceObserver:self
47 forGroup:PREF_GROUP_STATUS_PREFERENCES];
55 [previousStatusStateDict release];
56 [accountsToReconnect release];
58 [[adium notificationCenter] removeObserver:self];
59 [[adium preferenceController] unregisterPreferenceObserver:self];
64 * @brief Preferences changed
66 * Note whether we are supposed to change states after a specified time.
68 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
69 object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
72 autoAwayID = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_STATUS_STATE_ID] retain];
74 autoAway = (autoAwayID ?
75 [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY] boolValue] :
78 autoAwayInterval = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_INTERVAL] doubleValue];
82 * @brief Invoked when machine idle updates
84 * Invoked when Adium has an update on machine activity. If we are not yet idle, and the current length of inactivity
85 * is over the threshold, set our accounts to idle status.
87 - (void)machineIdleUpdate:(NSNotification *)notification
89 if (!automaticAwaySet && autoAway) {
90 double duration = [[[notification userInfo] objectForKey:@"Duration"] doubleValue];
92 //If we are over the away threshold, set our available accounts to away
93 if (duration > autoAwayInterval) {
94 NSEnumerator *enumerator;
96 AIStatusItem *targetStatusState;
98 if (!previousStatusStateDict) previousStatusStateDict = [[NSMutableDictionary alloc] init];
100 targetStatusState = [[adium statusController] statusStateWithUniqueStatusID:autoAwayID];
102 if ([targetStatusState isKindOfClass:[AIStatusGroup class]]) {
103 targetStatusState = [(AIStatusGroup *)targetStatusState anyContainedStatus];
106 if (targetStatusState) {
107 enumerator = [[[adium accountController] accounts] objectEnumerator];
108 while ((account = [enumerator nextObject])) {
109 AIStatus *currentStatusState = [account statusState];
110 if ([currentStatusState statusType] == AIAvailableStatusType) {
111 //Store the state the account is in at present
112 [previousStatusStateDict setObject:currentStatusState
113 forKey:[NSNumber numberWithUnsignedInt:[account hash]]];
115 if ([account online]) {
116 //If online, set the state
117 [account setStatusState:(AIStatus *)targetStatusState];
119 //If we just brought the account offline, note that it will need to be reconnected later
120 if ([targetStatusState statusType] == AIOfflineStatusType) {
121 if (!accountsToReconnect) accountsToReconnect = [[NSMutableSet alloc] init];
122 [accountsToReconnect addObject:account];
126 //If offline, set the state without coming online
127 [account setStatusStateAndRemainOffline:(AIStatus *)targetStatusState];
133 automaticAwaySet = YES;
139 * @brief Invoked when machine becomes active
141 * Invoked when Adium has an update on machine activity. Restore any status states we overrode with auto-away.
143 - (void)machineIsActive:(NSNotification *)notification
145 if (automaticAwaySet) {
146 NSEnumerator *enumerator;
149 enumerator = [[[adium accountController] accounts] objectEnumerator];
150 while ((account = [enumerator nextObject])) {
151 AIStatus *targetStatusState;
152 NSNumber *accountHash = [NSNumber numberWithUnsignedInt:[account hash]];
154 targetStatusState = [previousStatusStateDict objectForKey:accountHash];
155 if (targetStatusState) {
156 if ([account online] || [accountsToReconnect containsObject:account]) {
157 //If online or needs to be reconnected, set the previous state, going online if necessary
158 [account setStatusState:targetStatusState];
160 //If offline, set the state without coming online
161 [account setStatusStateAndRemainOffline:targetStatusState];
166 [previousStatusStateDict release]; previousStatusStateDict = nil;
167 [accountsToReconnect release]; accountsToReconnect = nil;
169 automaticAwaySet = NO;