summaryrefslogtreecommitdiffstats
blob: 46bc7b19cc8b8cd3a2037f20e2b3368b4371bfba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * Copyright (c) 2012 Tobias Markmann
 * Licensed under the simplified BSD license.
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 */

#include <SwifTools/Notifier/NotificationCenterNotifier.h>

#include <SwifTools/Notifier/NotificationCenterNotifierDelegate.h>

#import <Foundation/NSObjCRuntime.h>
#import <Foundation/NSUserNotification.h>
#import <Foundation/NSString.h>
#import <objc/runtime.h>

#include <boost/smart_ptr/make_shared.hpp>
#include <SwifTools/Cocoa/CocoaUtil.h>

#include <map>

#include <Swiften/Base/Log.h>

namespace Swift {

class NotificationCenterNotifier::Private {
	public:
		void handleNotificationClicked(NSUserNotification* notification) {
			unsigned long int id = [[[notification userInfo]  objectForKey:@"id"] unsignedLongValue];
			if (callbacks.find(id) != callbacks.end()) {
				callbacks[id]();
				callbacks.erase(id);
			} else {
				SWIFT_LOG(debug) << "Callback missing! id:"<< id << std::endl;
			}
		}

	public:
		unsigned long int lastID;
		NSUserNotificationCenter* notificationCenter;
		boost::intrusive_ptr<NotificationCenterNotifierDelegate> delegate;
		std::map<unsigned long int, boost::function<void()> > callbacks;
};

NotificationCenterNotifier::NotificationCenterNotifier(const std::string& /*name*/) {
	assert(isSupported());
	p = boost::make_shared<Private>();
	p->lastID = 0;
	p->delegate = boost::intrusive_ptr<NotificationCenterNotifierDelegate>([[NotificationCenterNotifierDelegate alloc] init], false);
	p->delegate.get().notifier = this;
	p->notificationCenter = [NSUserNotificationCenter defaultUserNotificationCenter];
	[p->notificationCenter setDelegate:p->delegate.get()];
}

NotificationCenterNotifier::~NotificationCenterNotifier() {

}

void NotificationCenterNotifier::showMessage(Notifier::Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& /* picture */, boost::function<void()> callback) {
	std::vector<Notifier::Type> defaultTypes = getDefaultTypes();
	if (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end()) {
		return;
	}

	unsigned long int currentID = ++(p->lastID);

	NSUserNotification *notification = [[NSUserNotification alloc] init];
	[notification setTitle: [NSString stringWithUTF8String:subject.c_str()]];
	[notification setInformativeText: [NSString stringWithUTF8String:description.c_str()]];
	//[notification setActionButtonTitle:@"Accept Invitation"];
	//[notification setHasActionButton:TRUE];
	//[notification setSoundName:NSUserNotificationDefaultSoundName];
	[notification setUserInfo: [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong:currentID] forKey:@"id"]];
	p->callbacks[currentID] = callback;
	[p->notificationCenter scheduleNotification:notification];
}

void NotificationCenterNotifier::purgeCallbacks() {
	p->callbacks.clear();
}

bool NotificationCenterNotifier::isSupported() {
	return NSClassFromString(@"NSUserNotificationCenter") != nil;
}

void NotificationCenterNotifier::handleNotificationClicked(void *notification) {
	p->handleNotificationClicked(static_cast<NSUserNotification*>(notification));
}

}