1
This repository has been archived on 2022-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Kim Wittenburg 15062dfb27 Archive Project
2017-07-25 17:21:13 +02:00

271 lines
10 KiB
Objective-C
Executable File

//
// NYTAppDelegate.m
// Notifications for YouTube
//
// Created by Kim Wittenburg on 09.07.13.
// Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//
#import "NYTAppDelegate.h"
// Core Imports
#import "NYTAuthentication.h"
#import "NYTUpdateManager.h"
// Other Imports
#import "NumberValueTransformer.h"
#import "NYTRulesWindowController.h"
@interface NYTAppDelegate ()
// Outlets etc.
@property (weak) IBOutlet NSButton *loginButton;
@property (readwrite, strong) NSStatusItem *statusItem;
// Login
@property (readwrite) BOOL loggingIn;
@end
// Notifications used for KVO
static void* const NYTLoginChangedNotification = @"NYTLoginChangedNotification";
static void* const NYTUpdateManagerPropertyDidChangeNotification = @"NYTUpdateManagerPropertyDidChangeNotification";
@implementation NYTAppDelegate {
NYTRulesWindowController *_rulesController;
}
+ (void)initialize
{
[super initialize];
// Register our value transformers
[NSValueTransformer setValueTransformer:[NumberValueTransformer new] forName:@"NumberValueTransformer"];
}
- (void)dealloc
{
// Make sure this object gets removed from any observed object
NYTUpdateManager *manager = [NYTUpdateManager sharedManager];
[manager removeObserver:self forKeyPath:@"autoRefreshEnabled"];
[manager removeObserver:self forKeyPath:@"autoRefreshInterval"];
[manager removeObserver:self forKeyPath:@"coalescesNotifications"];
[manager removeObserver:self forKeyPath:@"maximumVideoAge"];
[[NYTAuthentication sharedAuthentication] removeObserver:self forKeyPath:@"isLoggedIn"];
}
#pragma mark - Application Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NYTUpdateManager *manager = [NYTUpdateManager sharedManager];
NYTAuthentication *auth = [NYTAuthentication sharedAuthentication];
// Configure the User Defaults
NSDictionary *userDefaults = @{@"autoRefreshEnabled": @YES, @"autoRefreshInterval": @600, @"coalescesNotifications": @YES, @"maximumVideoAge": @3600};
[defaults registerDefaults:userDefaults];
// Configure Notification Centers
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
// Notification Startup
NSUserNotification *startNotification = aNotification.userInfo[NSApplicationLaunchUserNotificationKey];
if (startNotification) {
[self userNotificationCenter:[NSUserNotificationCenter defaultUserNotificationCenter] didActivateNotification:startNotification];
}
// Configure the status item
self.statusItemVisible = YES;
// Configure the login (and log in). Do so before configuring notifications or auto refresh because this can take a while
[auth addObserver:self forKeyPath:@"isLoggedIn" options:0 context:NYTLoginChangedNotification];
self.loggingIn = YES;
[auth tryLoginFromKeychainWithCompletionHandler:^{
self.loggingIn = NO;
// If there is no login in the keychain show the preferences
if (!auth.isLoggedIn) {
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[self.window makeKeyAndOrderFront:self];
}
}];
// Configure the update manager
manager.maximumVideoAge = [defaults integerForKey:@"maximumVideoAge"];
manager.coalescesNotifications = [defaults boolForKey:@"coalescesNotifications"];
manager.autoRefreshInterval = [defaults integerForKey:@"autoRefreshInterval"];
[manager addObserver:self forKeyPath:@"maximumVideoAge" options:NSKeyValueObservingOptionNew context:NYTUpdateManagerPropertyDidChangeNotification];
[manager addObserver:self forKeyPath:@"coalescesNotifications" options:NSKeyValueObservingOptionNew context:NYTUpdateManagerPropertyDidChangeNotification];
[manager addObserver:self forKeyPath:@"autoRefreshInterval" options:NSKeyValueObservingOptionNew context:NYTUpdateManagerPropertyDidChangeNotification];
// Configure (Auto) Refresh
manager.autoRefreshEnabled = [defaults boolForKey:@"autoRefreshEnabled"];
[manager addObserver:self forKeyPath:@"autoRefreshEnabled" options:NSKeyValueObservingOptionNew context:NYTUpdateManagerPropertyDidChangeNotification];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
{
// Open the preferences on reopen (if no other window is visible)
if (!flag) {
[self.window makeKeyAndOrderFront:nil];
}
return YES;
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - User Notification Center Delegate
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
// Show the URL
NSString *videoURL = notification.userInfo[NYTUserNotificationURLKey];
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:videoURL]];
// Remove the notification
[center removeDeliveredNotification:notification];
}
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
{
return YES;
}
#pragma mark -
#pragma mark *** Handling the Status Item ***
- (void)setStatusItemVisible:(BOOL)visible
{
if (visible) {
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
//NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:@"(4)"];
//[title addAttribute:NSStrokeWidthAttributeName value:@-5.0 range:NSMakeRange/*(3, 4)*/(1, 1)];
//self.statusItem.attributedTitle = title;
self.statusItem.image = [NSImage imageNamed:@"play-icon-bw"];
self.statusItem.alternateImage = [NSImage imageNamed:@"play-icon-s"];
self.statusItem.menu = self.statusMenu;
self.statusItem.highlightMode = YES;
} else {
[[NSStatusBar systemStatusBar] removeStatusItem:self.statusItem];
self.statusItem = nil;
}
}
- (BOOL)isStatusItemVisible
{
return self.statusItem != nil;
}
#pragma mark *** Handling Login ***
- (IBAction)login:(id)sender {
if ([NYTAuthentication sharedAuthentication].isLoggedIn) {
// Logout: Present a sheet giving the following options: Logout, Cancel, Switch user
NSString *title = NSLocalizedString(@"Do you want to log out or switch to another user?", nil);
NSString *switchUser = NSLocalizedString(@"Switch User…", nil);
NSString *logout = NSLocalizedString(@"Logout", nil);
NSString *cancel = NSLocalizedString(@"Cancel", nil);
NSString *msg = NSLocalizedString(@"If you logout the login stored in your keychain will be removed. You would have to log in agin the next time you want to use Notifications for YouTube.", nil);
NSBeginAlertSheet(title, switchUser, logout, cancel, self.window, self, NULL, @selector(sheetDidDismiss:returnCode:contextInfo:), NULL, @"%@", msg);
} else {
[self doLogin];
}
}
- (void)sheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if (returnCode == NSAlertDefaultReturn) {
// Switch User
[self doLogin];
} else if (returnCode == NSAlertAlternateReturn) {
// Logout: Redirect to Update Manager
[[NYTAuthentication sharedAuthentication] discardLogin];
}
}
- (void)doLogin
{
// Login: Redirect to Update Manager
self.loggingIn = YES;
[[NYTAuthentication sharedAuthentication] beginLoginSheetForWindow:self.window completionHandler:^(NSError *error) {
if (error) {
// Show the error as sheet if possible
if (self.window.isVisible) {
[NSApp presentError:error modalForWindow:self.window delegate:nil didPresentSelector:NULL contextInfo:NULL];
} else {
[NSApp presentError:error];
}
}
self.loggingIn = NO;
}];
}
#pragma mark *** Handling Refreshing ***
- (IBAction)performRefresh:(id)sender {
// Refresh with notifications
[[NYTUpdateManager sharedManager] refreshFeedsWithErrorHandler:^(NSError *error) {
// Show the error if the refresh was triggered manually
// Possibly show it in a modal sheet otherwise a modal window
if (error) {
if ([sender respondsToSelector:@selector(window)] && [sender window].isVisible) {
NSAlert *alert = [NSAlert alertWithError:error];
[alert beginSheetModalForWindow:[sender window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
} else {
[NSApp presentError:error];
}
}
} notify:YES];
}
#pragma mark *** Configure Notifications ***
- (IBAction)editRules:(id)sender {
_rulesController = [[NYTRulesWindowController alloc] init];
[NSApp beginSheet:_rulesController.window modalForWindow:self.window modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
// For efficiency reasons
_rulesController = nil;
}
#pragma mark *** Other Actions ***
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == NYTUpdateManagerPropertyDidChangeNotification) {
id value = change[NSKeyValueChangeNewKey];
[[NSUserDefaults standardUserDefaults] setObject:value forKey:keyPath];
}else if (context == NYTLoginChangedNotification) {
// Manage the title of the login/logout button based on wether login information is present (using KVO)
if ([NYTAuthentication sharedAuthentication].isLoggedIn) {
self.loginButton.title = NSLocalizedString(@"Logout…", nil);
} else {
self.loginButton.title = NSLocalizedString(@"Login…", nil);
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (IBAction)showPreferenceWindow:(id)sender
{
// Activate the app first
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[self.window makeKeyAndOrderFront:sender];
[self.window makeMainWindow];
}
- (IBAction)showAboutPanel:(id)sender {
[NSApp activateIgnoringOtherApps:YES];
[NSApp orderFrontStandardAboutPanel:sender];
}
- (IBAction)browseYouTube:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.youtube.com/"]];
}
@end