Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed 251010

Fixes from Matt Stevens:
"For background applications (menu bar, completely UI-less, etc) there are a couple of issues with Sparkle notifications:

- When prompts such as the initial prompt to enable update checking are displayed they can be hidden behind other windows since the background app is not in focus. This can cause problems, as these prompts run modally and can stop the application from functioning without the user knowing why.

- If the update notification window is displayed and the user clicks away to another application, the window disappears and there is no way to get it back since there is no other UI to cause the app to activate. In this case the update should probably operate as a standard window since it is effectively operating as the application's UI."
  • Loading branch information...
commit c42e3a3f476566bec351d2b02435700b0c082f0d 2 parents 675c66f + cec9166
@andymatuschak andymatuschak authored
Showing with 291 additions and 35 deletions.
  1. +3 −3 SUAutomaticUpdateAlert.m
  2. +3 −3 SUBasicUpdateDriver.h
  3. +3 −2 SUBasicUpdateDriver.m
  4. +1 −0  SUHost.h
  5. +5 −0 SUHost.m
  6. +3 −3 SUStatusController.m
  7. +2 −0  SUUIBasedUpdateDriver.h
  8. +22 −7 SUUIBasedUpdateDriver.m
  9. +3 −3 SUUpdateAlert.m
  10. +1 −1  SUUpdateDriver.h
  11. +1 −1  SUUpdatePermissionPrompt.h
  12. +10 −5 SUUpdatePermissionPrompt.m
  13. +16 −3 SUUserInitiatedUpdateDriver.m
  14. +1 −1  SUWindowController.h
  15. +2 −2 SUWindowController.m
  16. +1 −1  Sparkle.h
  17. +8 −0 Sparkle.xcodeproj/project.pbxproj
  18. +50 −0 sv.lproj/SUAutomaticUpdateAlert.nib/classes.nib
  19. +20 −0 sv.lproj/SUAutomaticUpdateAlert.nib/info.nib
  20. BIN  sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib
  21. BIN  sv.lproj/SUAutomaticUpdateAlert.strings
  22. +39 −0 sv.lproj/SUUpdateAlert.nib/classes.nib
  23. +18 −0 sv.lproj/SUUpdateAlert.nib/info.nib
  24. BIN  sv.lproj/SUUpdateAlert.nib/keyedobjects.nib
  25. BIN  sv.lproj/SUUpdateAlert.strings
  26. +59 −0 sv.lproj/SUUpdatePermissionPrompt.nib/classes.nib
  27. +20 −0 sv.lproj/SUUpdatePermissionPrompt.nib/info.nib
  28. BIN  sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib
  29. BIN  sv.lproj/Sparkle.strings
View
6 SUAutomaticUpdateAlert.m
@@ -11,14 +11,14 @@
@implementation SUAutomaticUpdateAlert
-- (id)initWithAppcastItem:(SUAppcastItem *)item host:(SUHost *)hb delegate:del;
+- (id)initWithAppcastItem:(SUAppcastItem *)item host:(SUHost *)aHost delegate:del;
{
- self = [super initWithHost:hb windowNibName:@"SUAutomaticUpdateAlert"];
+ self = [super initWithHost:aHost windowNibName:@"SUAutomaticUpdateAlert"];
if (self)
{
updateItem = [item retain];
delegate = del;
- host = [hb retain];
+ host = [aHost retain];
[self setShouldCascadeWindows:NO];
[[self window] center];
}
View
6 SUBasicUpdateDriver.h
@@ -22,7 +22,7 @@
NSString *relaunchPath;
}
-- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)hb;
+- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)host;
- (void)appcastDidFinishLoading:(SUAppcast *)ac;
- (void)appcast:(SUAppcast *)ac failedToLoadWithError:(NSError *)error;
@@ -44,8 +44,8 @@
- (void)unarchiverDidFail:(SUUnarchiver *)ua;
- (void)installUpdate;
-- (void)installerFinishedForHost:(SUHost *)hb;
-- (void)installerForHost:(SUHost *)hb failedWithError:(NSError *)error;
+- (void)installerFinishedForHost:(SUHost *)host;
+- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error;
- (void)relaunchHostApp;
- (void)cleanUp;
View
5 SUBasicUpdateDriver.m
@@ -166,8 +166,9 @@ - (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
- (BOOL)download:(NSURLDownload *)download shouldDecodeSourceDataOfMIMEType:(NSString *)encodingType
{
- if ([encodingType isEqualToString:@"application/gzip"]) return NO;
- return YES;
+ // We don't want the download system to extract our gzips.
+ // Note that we use a substring matching here instead of direct comparison because the docs say "application/gzip" but the system *uses* "application/x-gzip". This is a documentation bug.
+ return ([encodingType rangeOfString:@"gzip"].location == NSNotFound);
}
- (void)extractUpdate
View
1  SUHost.h
@@ -20,6 +20,7 @@
- (NSString *)displayVersion;
- (NSImage *)icon;
- (BOOL)isRunningOnReadOnlyVolume;
+- (BOOL)isBackgroundApplication;
- (NSString *)publicDSAKey;
- (NSArray *)systemProfile;
View
5 SUHost.m
@@ -85,6 +85,11 @@ - (BOOL)isRunningOnReadOnlyVolume
return (statfs_info.f_flags & MNT_RDONLY);
}
+- (BOOL)isBackgroundApplication
+{
+ return [[bundle objectForInfoDictionaryKey:@"LSUIElement"] doubleValue];
+}
+
- (NSString *)publicDSAKey
{
// Maybe the key is just a string in the Info.plist.
View
6 SUStatusController.m
@@ -11,12 +11,12 @@
@implementation SUStatusController
-- (id)initWithHost:(SUHost *)hb
+- (id)initWithHost:(SUHost *)aHost
{
- self = [super initWithHost:hb windowNibName:@"SUStatus"];
+ self = [super initWithHost:aHost windowNibName:@"SUStatus"];
if (self)
{
- host = [hb retain];
+ host = [aHost retain];
[self setShouldCascadeWindows:NO];
}
return self;
View
2  SUUIBasedUpdateDriver.h
@@ -18,6 +18,8 @@
SUUpdateAlert *updateAlert;
}
+- (void)showModalAlert:(NSAlert *)alert;
+
@end
#endif
View
29 SUUIBasedUpdateDriver.m
@@ -16,12 +16,19 @@ - (void)didFindValidUpdate
updateAlert = [[SUUpdateAlert alloc] initWithAppcastItem:updateItem host:host];
[updateAlert setDelegate:self];
- // If the app is a menubar app or the like, we need to focus it first:
- if ([[host objectForInfoDictionaryKey:@"LSUIElement"] doubleValue]) { [NSApp activateIgnoringOtherApps:YES]; }
-
SUUpdater *updater = [SUUpdater updaterForBundle:[host bundle]];
if ([[updater delegate] respondsToSelector:@selector(updater:didFindValidUpdate:)])
[[updater delegate] updater:updater didFindValidUpdate:updateItem];
+
+ // If the app is a menubar app or the like, we need to focus it first and alter the
+ // update prompt to behave like a normal window. Otherwise if the window were hidden
+ // there may be no way for the application to be activated to make it visible again.
+ if ([host isBackgroundApplication])
+ {
+ [[updateAlert window] setHidesOnDeactivate:NO];
+ [[updateAlert window] setLevel:NSNormalWindowLevel];
+ [NSApp activateIgnoringOtherApps:YES];
+ }
// Only show the update alert if the app is active; otherwise, we'll wait until it is.
if ([NSApp isActive])
@@ -36,8 +43,7 @@ - (void)didNotFindUpdate
if ([[updater delegate] respondsToSelector:@selector(updaterDidNotFindUpdate:)])
[[updater delegate] updaterDidNotFindUpdate:updater];
NSAlert *alert = [NSAlert alertWithMessageText:SULocalizedString(@"You're up to date!", nil) defaultButton:SULocalizedString(@"OK", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:SULocalizedString(@"%@ %@ is currently the newest version available.", nil), [host name], [host displayVersion]];
- [alert setIcon:[host icon]];
- [alert runModal];
+ [self showModalAlert:alert];
[self abortUpdate];
}
@@ -141,8 +147,7 @@ - (void)installUpdate
- (void)abortUpdateWithError:(NSError *)error
{
NSAlert *alert = [NSAlert alertWithMessageText:SULocalizedString(@"Update Error!", nil) defaultButton:SULocalizedString(@"Cancel Update", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:[error localizedDescription]];
- [alert setIcon:[host icon]];
- [alert runModal];
+ [self showModalAlert:alert];
[super abortUpdateWithError:error];
}
@@ -156,4 +161,14 @@ - (void)abortUpdate
[super abortUpdate];
}
+- (void)showModalAlert:(NSAlert *)alert
+{
+ // When showing a modal alert we need to ensure that background applications
+ // are focused to inform the user since there is no dock icon to notify them.
+ if ([host isBackgroundApplication]) { [NSApp activateIgnoringOtherApps:YES]; }
+
+ [alert setIcon:[host icon]];
+ [alert runModal];
+}
+
@end
View
6 SUUpdateAlert.m
@@ -13,12 +13,12 @@
@implementation SUUpdateAlert
-- (id)initWithAppcastItem:(SUAppcastItem *)item host:(SUHost *)hb
+- (id)initWithAppcastItem:(SUAppcastItem *)item host:(SUHost *)aHost
{
- self = [super initWithHost:hb windowNibName:@"SUUpdateAlert"];
+ self = [super initWithHost:host windowNibName:@"SUUpdateAlert"];
if (self)
{
- host = [hb retain];
+ host = [aHost retain];
updateItem = [item retain];
[self setShouldCascadeWindows:NO];
}
View
2  SUUpdateDriver.h
@@ -20,7 +20,7 @@ extern NSString *SUUpdateDriverFinishedNotification;
BOOL finished;
}
-- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)hb;
+- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)host;
- (void)abortUpdate;
- (BOOL)finished;
View
2  SUUpdatePermissionPrompt.h
@@ -25,7 +25,7 @@ typedef enum {
IBOutlet NSButton *moreInfoButton;
BOOL isShowingMoreInfo, shouldSendProfile;
}
-+ (void)promptWithHost:(SUHost *)hb delegate:(id)d;
++ (void)promptWithHost:(SUHost *)aHost delegate:(id)d;
- (IBAction)toggleMoreInfo:(id)sender;
- (IBAction)finishPrompt:(id)sender;
@end
View
15 SUUpdatePermissionPrompt.m
@@ -16,12 +16,12 @@ - (BOOL)shouldAskAboutProfile
return [[host objectForInfoDictionaryKey:SUEnableSystemProfilingKey] boolValue];
}
-- (id)initWithHost:(SUHost *)hb delegate:(id)d
+- (id)initWithHost:(SUHost *)aHost delegate:(id)d
{
- self = [super initWithHost:hb windowNibName:@"SUUpdatePermissionPrompt"];
+ self = [super initWithHost:aHost windowNibName:@"SUUpdatePermissionPrompt"];
if (self)
{
- host = [hb retain];
+ host = [aHost retain];
delegate = [d retain];
isShowingMoreInfo = NO;
shouldSendProfile = [self shouldAskAboutProfile];
@@ -30,9 +30,14 @@ - (id)initWithHost:(SUHost *)hb delegate:(id)d
return self;
}
-+ (void)promptWithHost:(SUHost *)hb delegate:(id)d
++ (void)promptWithHost:(SUHost *)host delegate:(id)d
{
- id prompt = [[[self class] alloc] initWithHost:hb delegate:d];
+ // If this is a background application we need to focus it in order to bring the prompt
+ // to the user's attention. Otherwise the prompt would be hidden behind other applications and
+ // the user would not know why the application was paused.
+ if ([host isBackgroundApplication]) { [NSApp activateIgnoringOtherApps:YES]; }
+
+ id prompt = [[[self class] alloc] initWithHost:host delegate:d];
[NSApp runModalForWindow:[prompt window]];
}
View
19 SUUserInitiatedUpdateDriver.m
@@ -11,14 +11,21 @@
@implementation SUUserInitiatedUpdateDriver
-- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)hb
+- (void)checkForUpdatesAtURL:(NSURL *)appcastURL host:(SUHost *)aHost
{
- checkingController = [[SUStatusController alloc] initWithHost:hb];
+ checkingController = [[SUStatusController alloc] initWithHost:aHost];
[[checkingController window] center]; // Force the checking controller to load its window.
[checkingController beginActionWithTitle:SULocalizedString(@"Checking for updates\u2026", nil) maxProgressValue:0 statusText:nil];
[checkingController setButtonTitle:SULocalizedString(@"Cancel", nil) target:self action:@selector(cancelCheckForUpdates:) isDefault:NO];
[checkingController showWindow:self];
- [super checkForUpdatesAtURL:appcastURL host:hb];
+ [super checkForUpdatesAtURL:appcastURL host:host];
+
+ // For background applications, obtain focus.
+ // Useful if the update check is requested from another app like System Preferences.
+ if ([host isBackgroundApplication])
+ {
+ [NSApp activateIgnoringOtherApps:YES];
+ }
}
- (void)closeCheckingWindow
@@ -54,6 +61,12 @@ - (void)abortUpdateWithError:(NSError *)error
[super abortUpdateWithError:error];
}
+- (void)abortUpdate
+{
+ [self closeCheckingWindow];
+ [super abortUpdate];
+}
+
- (void)appcast:(SUAppcast *)ac failedToLoadWithError:(NSError *)error
{
if (isCanceled)
View
2  SUWindowController.h
@@ -14,7 +14,7 @@
@class SUHost;
@interface SUWindowController : NSWindowController { }
// We use this instead of plain old NSWindowController initWithWindowNibName so that we'll be able to find the right path when running in a bundle loaded from another app.
-- (id)initWithHost:(SUHost *)hb windowNibName:(NSString *)nibName;
+- (id)initWithHost:(SUHost *)host windowNibName:(NSString *)nibName;
@end
#endif
View
4 SUWindowController.m
@@ -10,12 +10,12 @@
@implementation SUWindowController
-- (id)initWithHost:(SUHost *)hb windowNibName:(NSString *)nibName
+- (id)initWithHost:(SUHost *)host windowNibName:(NSString *)nibName
{
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:nibName ofType:@"nib"];
if (path == nil) // Slight hack to resolve issues with running Sparkle in debug configurations.
{
- NSString *frameworkPath = [[hb sharedFrameworksPath] stringByAppendingPathComponent:@"Sparkle.framework"];
+ NSString *frameworkPath = [[host sharedFrameworksPath] stringByAppendingPathComponent:@"Sparkle.framework"];
NSBundle *framework = [NSBundle bundleWithPath:frameworkPath];
path = [framework pathForResource:nibName ofType:@"nib"];
}
View
2  Sparkle.h
@@ -13,7 +13,7 @@
#ifndef SPARKLE_H
#define SPARKLE_H
-#define SULocalizedString(key,comment) NSLocalizedStringFromTableInBundle(key, @"Sparkle", [NSBundle bundleForClass:[self class]], comment)
+#define SULocalizedString(key,comment) NSLocalizedStringFromTableInBundle(key, @"Sparkle", [NSBundle bundleWithIdentifier:@"org.andymatuschak.Sparkle"], comment)
#define SUAbstractFail() NSAssert2(nil, @"Can't call %@ on an instance of %@; this is an abstract method!", __PRETTY_FUNCTION__, [self class]);
#ifdef __OBJC__
View
8 Sparkle.xcodeproj/project.pbxproj
@@ -189,6 +189,10 @@
615AE3CF0D64DC40001CA7BD /* SUModelTranslation.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SUModelTranslation.plist; sourceTree = "<group>"; };
6171D9050D57B81800BFE886 /* NSFileManager+Aliases.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+Aliases.h"; sourceTree = "<group>"; };
6171D9060D57B81800BFE886 /* NSFileManager+Aliases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+Aliases.m"; sourceTree = "<group>"; };
+ 618915700E35937600B5E981 /* sv */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = sv; path = sv.lproj/SUUpdatePermissionPrompt.nib; sourceTree = "<group>"; };
+ 618915710E35937600B5E981 /* sv */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = sv; path = sv.lproj/SUUpdateAlert.nib; sourceTree = "<group>"; };
+ 618915720E35937600B5E981 /* sv */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = sv; path = sv.lproj/SUAutomaticUpdateAlert.nib; sourceTree = "<group>"; };
+ 618915730E35937600B5E981 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Sparkle.strings; sourceTree = "<group>"; };
618FA4FF0DAE88B40026945C /* SUInstaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUInstaller.h; sourceTree = "<group>"; };
618FA5000DAE88B40026945C /* SUInstaller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUInstaller.m; sourceTree = "<group>"; };
618FA5030DAE8AB80026945C /* SUPlainInstaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUPlainInstaller.h; sourceTree = "<group>"; };
@@ -880,6 +884,7 @@
61AAE8710A321F7700D8810D /* nl */,
619B17200E1E9D0800E72754 /* de */,
61F614540E24A12D009F47E7 /* it */,
+ 618915730E35937600B5E981 /* sv */,
);
name = Sparkle.strings;
sourceTree = "<group>";
@@ -893,6 +898,7 @@
61F365350E1898A3007ECA02 /* nl */,
619B17210E1E9D0800E72754 /* de */,
61F614550E24A12D009F47E7 /* it */,
+ 618915720E35937600B5E981 /* sv */,
);
name = SUAutomaticUpdateAlert.nib;
sourceTree = "<group>";
@@ -906,6 +912,7 @@
61F365340E1898A3007ECA02 /* nl */,
619B17220E1E9D0800E72754 /* de */,
61F614560E24A12D009F47E7 /* it */,
+ 618915710E35937600B5E981 /* sv */,
);
name = SUUpdateAlert.nib;
sourceTree = "<group>";
@@ -935,6 +942,7 @@
61F365330E1898A3007ECA02 /* nl */,
619B17230E1E9D0800E72754 /* de */,
61F614570E24A12D009F47E7 /* it */,
+ 618915700E35937600B5E981 /* sv */,
);
name = SUUpdatePermissionPrompt.nib;
sourceTree = "<group>";
View
50 sv.lproj/SUAutomaticUpdateAlert.nib/classes.nib
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBClasses</key>
+ <array>
+ <dict>
+ <key>CLASS</key>
+ <string>SUWindowController</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSWindowController</string>
+ </dict>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>doNotInstall</key>
+ <string>id</string>
+ <key>installLater</key>
+ <string>id</string>
+ <key>installNow</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>SUAutomaticUpdateAlert</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>SUWindowController</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>NSObject</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ </dict>
+ </array>
+ <key>IBVersion</key>
+ <string>1</string>
+</dict>
+</plist>
View
20 sv.lproj/SUAutomaticUpdateAlert.nib/info.nib
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>670</string>
+ <key>IBLastKnownRelativeProjectPath</key>
+ <string>../Sparkle.xcodeproj</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>6</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>10A96</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
View
BIN  sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib
Binary file not shown
View
BIN  sv.lproj/SUAutomaticUpdateAlert.strings
Binary file not shown
View
39 sv.lproj/SUUpdateAlert.nib/classes.nib
@@ -0,0 +1,39 @@
+{
+ IBClasses = (
+ {
+ CLASS = FirstResponder;
+ LANGUAGE = ObjC;
+ SUPERCLASS = NSObject;
+ },
+ {
+ CLASS = NSApplication;
+ LANGUAGE = ObjC;
+ SUPERCLASS = NSResponder;
+ },
+ {
+ CLASS = NSObject;
+ LANGUAGE = ObjC;
+ },
+ {
+ ACTIONS = {
+ installUpdate = id;
+ remindMeLater = id;
+ skipThisVersion = id;
+ };
+ CLASS = SUUpdateAlert;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ delegate = id;
+ description = NSTextField;
+ releaseNotesView = WebView;
+ };
+ SUPERCLASS = SUWindowController;
+ },
+ {
+ CLASS = SUWindowController;
+ LANGUAGE = ObjC;
+ SUPERCLASS = NSWindowController;
+ }
+ );
+ IBVersion = 1;
+}
View
18 sv.lproj/SUUpdateAlert.nib/info.nib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>69 14 356 240 0 0 1280 778 </string>
+ <key>IBFramework Version</key>
+ <string>489.0</string>
+ <key>IBLastKnownRelativeProjectPath</key>
+ <string>../Sparkle.xcodeproj</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBSystem Version</key>
+ <string>9D34</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
View
BIN  sv.lproj/SUUpdateAlert.nib/keyedobjects.nib
Binary file not shown
View
BIN  sv.lproj/SUUpdateAlert.strings
Binary file not shown
View
59 sv.lproj/SUUpdatePermissionPrompt.nib/classes.nib
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBClasses</key>
+ <array>
+ <dict>
+ <key>CLASS</key>
+ <string>SUWindowController</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSWindowController</string>
+ </dict>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>finishPrompt</key>
+ <string>id</string>
+ <key>toggleMoreInfo</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>SUUpdatePermissionPrompt</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>OUTLETS</key>
+ <dict>
+ <key>delegate</key>
+ <string>id</string>
+ <key>descriptionTextField</key>
+ <string>NSTextField</string>
+ <key>moreInfoButton</key>
+ <string>NSButton</string>
+ <key>moreInfoView</key>
+ <string>NSView</string>
+ </dict>
+ <key>SUPERCLASS</key>
+ <string>SUWindowController</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>NSObject</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ </dict>
+ </array>
+ <key>IBVersion</key>
+ <string>1</string>
+</dict>
+</plist>
View
20 sv.lproj/SUUpdatePermissionPrompt.nib/info.nib
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>670</string>
+ <key>IBLastKnownRelativeProjectPath</key>
+ <string>../Sparkle.xcodeproj</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>6</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>10A96</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
View
BIN  sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib
Binary file not shown
View
BIN  sv.lproj/Sparkle.strings
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.