Source/CBContactLastSeenPlugin.m
author Evan Schoenberg
Sat Oct 31 13:13:20 2009 -0500 (2009-10-31)
changeset 2707 6ed082e67639
parent 1946 866f1f27b315
permissions -rw-r--r--
Patch from '''egladil''', with some tweaking by me, to improve out "last seen" monitoring to understand metacontacts and update the values accordingly. Thanks!

Fixes #11652
David@0
     1
/* 
David@0
     2
 * Adium is the legal property of its developers, whose names are listed in the copyright file included
David@0
     3
 * with this source distribution.
David@0
     4
 * 
David@0
     5
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
David@0
     6
 * General Public License as published by the Free Software Foundation; either version 2 of the License,
David@0
     7
 * or (at your option) any later version.
David@0
     8
 * 
David@0
     9
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
David@0
    10
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
David@0
    11
 * Public License for more details.
David@0
    12
 * 
David@0
    13
 * You should have received a copy of the GNU General Public License along with this program; if not,
David@0
    14
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
David@0
    15
 */
David@0
    16
David@0
    17
#import <Adium/AIInterfaceControllerProtocol.h>
David@0
    18
#import "CBContactLastSeenPlugin.h"
David@0
    19
#import <AIUtilities/AIDateFormatterAdditions.h>
David@0
    20
#import <Adium/AIListObject.h>
Evan@2707
    21
#import <Adium/AIMetaContact.h>
David@0
    22
David@0
    23
#define PREF_GROUP_LAST_SEEN	@"Last Seen"
David@0
    24
#define KEY_LAST_SEEN_STATUS	@"Last Seen Status"
David@0
    25
#define KEY_LAST_SEEN_DATE		@"Last Seen Date"
David@0
    26
David@0
    27
/*!
David@0
    28
 * @class CBContactLastSeenPlugin
David@0
    29
 * @brief Component to track and display as a tooltip the last time contacts were seen online
David@0
    30
 */
David@0
    31
@implementation CBContactLastSeenPlugin
David@0
    32
David@0
    33
/*!
David@0
    34
 * @brief Install
David@0
    35
 */
David@0
    36
- (void)installPlugin
David@0
    37
{
David@0
    38
    //Install our tooltip entry
David@100
    39
    [adium.interfaceController registerContactListTooltipEntry:self secondaryEntry:NO];
David@0
    40
Evan@2707
    41
	//Observe status changes
Evan@2707
    42
    [[AIContactObserverManager sharedManager] registerListObjectObserver:self];
David@0
    43
}
David@0
    44
Evan@2707
    45
- (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
David@0
    46
{
Evan@2707
    47
	/* Update only for contacts whose online status has changed */
Evan@2707
    48
	if ([inObject isKindOfClass:[AIListContact class]]) {
Evan@2707
    49
		if ([inModifiedKeys containsObject:@"Online"]) {
Evan@2707
    50
			if (inObject.online) {
Evan@2707
    51
				//Either they are online, or we've come online. Either way, update both their status and the time
Evan@2707
    52
				[inObject setPreference:AILocalizedString(@"Online",nil)
Evan@2707
    53
								 forKey:KEY_LAST_SEEN_STATUS
Evan@2707
    54
								  group:PREF_GROUP_LAST_SEEN];
Evan@2707
    55
				
Evan@2707
    56
				[inObject setPreference:[NSDate date]
Evan@2707
    57
								 forKey:KEY_LAST_SEEN_DATE
Evan@2707
    58
								  group:PREF_GROUP_LAST_SEEN];
Evan@2707
    59
				
Evan@2707
    60
				
Evan@2707
    61
			} else {
Evan@2707
    62
				if (!silent) {
Evan@2707
    63
					//They've signed off, update their status and the time		
Evan@2707
    64
					[inObject setPreference:AILocalizedString(@"Signing off",nil)
Evan@2707
    65
									 forKey:KEY_LAST_SEEN_STATUS
Evan@2707
    66
									  group:PREF_GROUP_LAST_SEEN];
Evan@2707
    67
					
Evan@2707
    68
					[inObject setPreference:[NSDate date]
Evan@2707
    69
									 forKey:KEY_LAST_SEEN_DATE
Evan@2707
    70
									  group:PREF_GROUP_LAST_SEEN];	
Evan@2707
    71
				} else {
Evan@2707
    72
					/* Don't update the status, as we didn't see them signing off but
Evan@2707
    73
					 * rather we signed off (silent updates are grouped ones.)
Evan@2707
    74
					 * Just update the date.
Evan@2707
    75
					 */
Evan@2707
    76
					[inObject setPreference:[NSDate date]
Evan@2707
    77
									 forKey:KEY_LAST_SEEN_DATE
Evan@2707
    78
									  group:PREF_GROUP_LAST_SEEN];
Evan@2707
    79
				}
Evan@2707
    80
			}
Evan@2707
    81
		}
Evan@2707
    82
	}
David@0
    83
	
Evan@2707
    84
	return nil;	
David@0
    85
}
David@0
    86
David@0
    87
#pragma mark Tooltip entry
David@0
    88
//Tooltip entry ---------------------------------------------------------------------------------------
David@0
    89
David@0
    90
/*!
David@0
    91
 * @brief Tooltip label
David@0
    92
 *
David@0
    93
 * @result A label, or nil if no tooltip entry should be shown
David@0
    94
 */
David@0
    95
- (NSString *)labelForObject:(AIListObject *)inObject
David@0
    96
{
David@0
    97
    return AILocalizedString(@"Last Seen","A time interval such as '4 days ago' will be shown after this tooltip identifier");
David@0
    98
}
David@0
    99
David@0
   100
/*!
David@0
   101
 * @brief Tooltip entry
David@0
   102
 *
David@0
   103
 * @result The tooltip entry, or nil if no tooltip should be shown
David@0
   104
 */
David@0
   105
- (NSAttributedString *)entryForObject:(AIListObject *)inObject
David@0
   106
{
David@0
   107
	NSString			*lastSeenStatus;
David@0
   108
	NSDate				*lastSeenDate;
David@0
   109
	NSDateFormatter		*sinceDateFormatter;
David@0
   110
	NSAttributedString	*entry = nil;
David@0
   111
	
David@0
   112
	//Only display for offline contacts
David@837
   113
	if (!inObject.online) {
David@0
   114
	
David@95
   115
		lastSeenStatus = [adium.preferenceController preferenceForKey:KEY_LAST_SEEN_STATUS 
David@0
   116
																  group:PREF_GROUP_LAST_SEEN
David@0
   117
																 object:inObject];
David@0
   118
		
David@95
   119
		lastSeenDate = [adium.preferenceController preferenceForKey:KEY_LAST_SEEN_DATE 
David@0
   120
																group:PREF_GROUP_LAST_SEEN
David@0
   121
															   object:inObject];
David@0
   122
		if (lastSeenStatus && lastSeenDate) {
David@0
   123
			NSString	*timeElapsed;
David@0
   124
			NSString	*timeElapsedWithDesignation;
David@0
   125
			
David@0
   126
			sinceDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
David@0
   127
			[sinceDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
David@0
   128
			[sinceDateFormatter setDateFormat:[NSString stringWithFormat:@"%@, %@",
David@0
   129
											   [[NSDateFormatter localizedShortDateFormatter] dateFormat],
David@0
   130
											   [NSDateFormatter localizedDateFormatStringShowingSeconds:NO showingAMorPM:YES]]];
David@0
   131
			
David@0
   132
			//stringForTimeIntervalSinceDate may return @"" if it's too short of an interval.
David@0
   133
			timeElapsed = [NSDateFormatter stringForTimeIntervalSinceDate:lastSeenDate showingSeconds:NO abbreviated:NO];
David@0
   134
			if (timeElapsed && [timeElapsed length]) {
David@0
   135
				timeElapsedWithDesignation = [NSString stringWithFormat:
David@0
   136
					AILocalizedString(@"%@ ago", "%@ will be replaced by an amount of time such as '1 day, 4 hours'. This string is used in the 'Last Seen:' information shown when hovering over an offline contact."),
David@0
   137
					timeElapsed];
David@0
   138
			} else {
David@0
   139
				timeElapsedWithDesignation = @"";
David@0
   140
			}
David@0
   141
			
David@0
   142
			
David@0
   143
			entry = [[NSAttributedString alloc] 
David@0
   144
						initWithString:[NSString stringWithFormat:
David@0
   145
							@"%@\n%@%@%@", 
David@0
   146
							lastSeenStatus,
David@0
   147
							timeElapsedWithDesignation,
David@0
   148
							([timeElapsedWithDesignation length] ? @"\n" : @""),
David@0
   149
							[sinceDateFormatter stringForObjectValue:lastSeenDate]]]; 
David@0
   150
		}
David@0
   151
	}
David@0
   152
	
David@0
   153
	return [entry autorelease];
David@0
   154
}
David@0
   155
David@0
   156
- (BOOL)shouldDisplayInContactInspector
David@0
   157
{
David@0
   158
	return YES;
David@0
   159
}
David@0
   160
David@0
   161
@end