Merge pull request #254 from MarkJerde/various_fixes

Various fixes
This commit is contained in:
Gennadii Potapov 2022-01-24 13:12:24 +08:00 committed by GitHub
commit 696178a7ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 741 additions and 381 deletions

View file

@ -22,7 +22,7 @@
@class SGHotKey; @class SGHotKey;
@interface AppController : NSObject <NSMenuDelegate, NSApplicationDelegate, NSAlertDelegate, FlycutStoreDelegate, FlycutOperatorDelegate, BezelWindowDelegate> { @interface AppController : NSObject <NSMenuDelegate, NSApplicationDelegate, FlycutStoreDelegate, FlycutOperatorDelegate, BezelWindowDelegate> {
BezelWindow *bezel; BezelWindow *bezel;
SGHotKey *mainHotKey; SGHotKey *mainHotKey;
IBOutlet SRRecorderControl *mainRecorder; IBOutlet SRRecorderControl *mainRecorder;
@ -45,9 +45,13 @@
NSString *statusItemText; NSString *statusItemText;
NSImage *statusItemImage; NSImage *statusItemImage;
IBOutlet NSTextField *savingSectionLabel;
IBOutlet NSTextField *saveFromBezelToLabel;
IBOutlet NSTextField *forgottenItemLabel; IBOutlet NSTextField *forgottenItemLabel;
IBOutlet NSButton *forgottenFavoritesCheckbox; IBOutlet NSButton *forgottenFavoritesCheckbox;
IBOutlet NSButton *forgottenClippingsCheckbox; IBOutlet NSButton *forgottenClippingsCheckbox;
IBOutlet NSButton *saveToLocationButton;
IBOutlet NSButton *autoSaveToLocationButton;
// The menu attatched to same // The menu attatched to same
IBOutlet NSMenu *jcMenu; IBOutlet NSMenu *jcMenu;
int jcMenuBaseItemsCount; int jcMenuBaseItemsCount;
@ -75,6 +79,8 @@
BOOL needMenuUpdate; BOOL needMenuUpdate;
} }
+ (BOOL)isAppSandboxed;
// Basic functionality // Basic functionality
-(void) pollPB:(NSTimer *)timer; -(void) pollPB:(NSTimer *)timer;
-(void) addClipToPasteboard:(NSString*)pbFullText; -(void) addClipToPasteboard:(NSString*)pbFullText;

View file

@ -26,6 +26,15 @@
@implementation AppController @implementation AppController
/// Determines, through a hack of sorts, if the app is running sandboxed. The SANDBOXING define has no direct connection to being sandboxed, but this method identifies the state by looking for a directory which will have at least eight path components if sandboxed and is quite unlikely to have that many if not sandboxed. Of course, if this doesn't work for your unique case, just do a custom build with this method returning NO.
+ (BOOL)isAppSandboxed {
// Get the Desktop directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDesktopDirectory, NSUserDomainMask, YES);
NSString *desktopDirectory = [paths objectAtIndex:0];
return ((NSArray*)[desktopDirectory componentsSeparatedByString:@"/"]).count >= 8;
}
- (id)init - (id)init
{ {
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys: [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
@ -134,6 +143,7 @@
- (void)showOldOSXAlert { - (void)showOldOSXAlert {
// FIXME: Should ask Gennadii if the "#ifdef SANDBOXING" should be removed and replaced with "if (![AppController isAppSandboxed]) { return; }"
#ifdef SANDBOXING #ifdef SANDBOXING
NSOperatingSystemVersion ver = [[NSProcessInfo processInfo] operatingSystemVersion]; NSOperatingSystemVersion ver = [[NSProcessInfo processInfo] operatingSystemVersion];
if (ver.majorVersion == 10 && ver.minorVersion <= 13) { if (ver.majorVersion == 10 && ver.minorVersion <= 13) {
@ -224,6 +234,7 @@
// The load-on-startup check can be really slow, so this will be dispatched out so our thread isn't blocked. // The load-on-startup check can be really slow, so this will be dispatched out so our thread isn't blocked.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{ dispatch_async(queue, ^{
// FIXME: Should ask Gennadii if the "#ifdef SANDBOXING" should be removed and replaced with "if ([AppController isAppSandboxed])"
#ifdef SANDBOXING #ifdef SANDBOXING
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bundleIdentifier == %@", kFlycutHelperId]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bundleIdentifier == %@", kFlycutHelperId];
NSArray *helperApp = [[[NSWorkspace sharedWorkspace] runningApplications] filteredArrayUsingPredicate:predicate]; NSArray *helperApp = [[[NSWorkspace sharedWorkspace] runningApplications] filteredArrayUsingPredicate:predicate];
@ -245,9 +256,9 @@
}); });
[self registerOrDeregisterICloudSync]; [self registerOrDeregisterICloudSync];
// Check if the app has Accessibility permission
[NSApp activateIgnoringOtherApps: YES]; [NSApp activateIgnoringOtherApps: YES];
// Check if the app has Accessibility permission
[self showAccessibilityAlert]; [self showAccessibilityAlert];
[self showOldOSXAlert]; [self showOldOSXAlert];
} }
@ -664,10 +675,22 @@
[appearancePanel addSubview:row]; [appearancePanel addSubview:row];
nextYMax = row.frame.origin.y; nextYMax = row.frame.origin.y;
#ifdef SANDBOXING #ifdef SANDBOXING
// Hide the Save Clippings preferences. These work fine when sandboxed. They just save to somwehere under ~/Library/Containers. If SANDBOXING isn't set, automatic saving of forgotten clippings will go somewhere under ~/Library/Containers while manual saving (s or S in the bezel) will open an NSSavePanel to prompt the user to pick.
forgottenItemLabel.hidden = YES; forgottenItemLabel.hidden = YES;
forgottenClippingsCheckbox.hidden = YES; forgottenClippingsCheckbox.hidden = YES;
forgottenFavoritesCheckbox.hidden = YES; forgottenFavoritesCheckbox.hidden = YES;
savingSectionLabel.hidden = YES;
saveToLocationButton.hidden = YES;
autoSaveToLocationButton.hidden = YES;
saveFromBezelToLabel.hidden = YES;
#endif #endif
if ([AppController isAppSandboxed]) {
// Saving to a prior-selected location while sandboxed would be unpleasant, so these really should be disabled always when sandboxed but can still show where the saves happen so the user knows what to expect.
saveToLocationButton.enabled = NO;
[saveToLocationButton setTitle:@"Ask User"];
autoSaveToLocationButton.enabled = NO;
[autoSaveToLocationButton setTitle:@"App Sandbox"];
}
} }
-(IBAction) showPreferencePanel:(id)sender -(IBAction) showPreferencePanel:(id)sender
@ -683,19 +706,32 @@
encoding:NSUTF8StringEncoding encoding:NSUTF8StringEncoding
error:NULL]; error:NULL];
[acknowledgementsView setString:contents]; [acknowledgementsView setString:contents];
if (![AppController isAppSandboxed]) {
NSURL* saveToLocation = [[NSUserDefaults standardUserDefaults] URLForKey:@"saveToLocation"];
if (saveToLocation) {
[saveToLocationButton setTitle:[saveToLocation lastPathComponent]];
}
NSURL* autoSaveToLocation = [[NSUserDefaults standardUserDefaults] URLForKey:@"autoSaveToLocation"];
if (autoSaveToLocation) {
[autoSaveToLocationButton setTitle:[autoSaveToLocation lastPathComponent]];
}
}
[flycutOperator willShowPreferences]; [flycutOperator willShowPreferences];
} }
-(IBAction)toggleLoadOnStartup:(id)sender { -(IBAction)toggleLoadOnStartup:(id)sender {
// Since the control in Interface Builder is bound to User Defaults and sends this action, this method is called after User Defaults already reflects the newly-selected state and merely conveys that value to the relevant mechanisms rather than acting to negate the User Defaults state.
if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"loadOnStartup"] ) { if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"loadOnStartup"] ) {
// FIXME: Should ask Gennadii if the "#ifdef SANDBOXING" should be removed and replaced with "if ([AppController isAppSandboxed])"
#ifdef SANDBOXING #ifdef SANDBOXING
SMLoginItemSetEnabled((__bridge CFStringRef)kFlycutHelperId, YES); SMLoginItemSetEnabled((__bridge CFStringRef)kFlycutHelperId, YES);
#else #else
[UKLoginItemRegistry addLoginItemWithPath:[[NSBundle mainBundle] bundlePath] hideIt:NO]; [UKLoginItemRegistry addLoginItemWithPath:[[NSBundle mainBundle] bundlePath] hideIt:NO];
#endif #endif
} else { } else {
// FIXME: Should ask Gennadii if the "#ifdef SANDBOXING" should be removed and replaced with "if ([AppController isAppSandboxed])"
#ifdef SANDBOXING #ifdef SANDBOXING
SMLoginItemSetEnabled((__bridge CFStringRef)kFlycutHelperId, YES); SMLoginItemSetEnabled((__bridge CFStringRef)kFlycutHelperId, NO);
#else #else
[UKLoginItemRegistry removeLoginItemWithPath:[[NSBundle mainBundle] bundlePath]]; [UKLoginItemRegistry removeLoginItemWithPath:[[NSBundle mainBundle] bundlePath]];
#endif #endif
@ -857,7 +893,7 @@
if (largeCopyRisk) if (largeCopyRisk)
[self toggleMenuIconDisabled]; [self toggleMenuIconDisabled];
if ( contents == nil || [flycutOperator shouldSkip:contents ofType:[jcPasteboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]] ) { if ( contents == nil || [flycutOperator shouldSkip:contents ofType:[jcPasteboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] fromAvailableTypes:[jcPasteboard types]] ) {
DLog(@"Contents: Empty or skipped"); DLog(@"Contents: Empty or skipped");
} else if ( ! [pbCount isEqualTo:pbBlockCount] ) { } else if ( ! [pbCount isEqualTo:pbBlockCount] ) {
[flycutOperator addClipping:contents ofType:type fromApp:[currRunningApp localizedName] withAppBundleURL:currRunningApp.bundleURL.path target:self clippingAddedSelector:@selector(updateMenu)]; [flycutOperator addClipping:contents ofType:type fromApp:[currRunningApp localizedName] withAppBundleURL:currRunningApp.bundleURL.path target:self clippingAddedSelector:@selector(updateMenu)];
@ -1177,6 +1213,37 @@ didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
} }
} }
- (IBAction)selectSaveLocation:(id)sender {
// Create and configure the panel.
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel retain];
[panel setCanChooseFiles:NO];
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:YES];
[panel setAllowsMultipleSelection:NO];
[panel setMessage:@"Select a directory."];
// Display the panel attached to the document's window.
[panel beginSheetModalForWindow:prefsPanel completionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
NSURL* url = [[panel URLs] firstObject];
[panel release];
if (!url) { return; }
if (sender == saveToLocationButton) {
[[NSUserDefaults standardUserDefaults] setURL:url forKey:@"saveToLocation"];
}
else if (sender == autoSaveToLocationButton) {
[[NSUserDefaults standardUserDefaults] setURL:url forKey:@"autoSaveToLocation"];
}
[sender setTitle:[url lastPathComponent]];
}
}];
}
-(IBAction)clearClippingList:(id)sender { -(IBAction)clearClippingList:(id)sender {
int choice; int choice;

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19162" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19162"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -97,12 +97,16 @@
<connections> <connections>
<outlet property="acknowledgementsView" destination="357" id="2y8-wF-wPX"/> <outlet property="acknowledgementsView" destination="357" id="2y8-wF-wPX"/>
<outlet property="appearancePanel" destination="EFy-pc-aKl" id="NYD-Y7-bfQ"/> <outlet property="appearancePanel" destination="EFy-pc-aKl" id="NYD-Y7-bfQ"/>
<outlet property="autoSaveToLocationButton" destination="PJD-Fc-76A" id="UqW-Sy-cr5"/>
<outlet property="forgottenClippingsCheckbox" destination="LLh-vf-2Q3" id="JMi-Mi-Nlx"/> <outlet property="forgottenClippingsCheckbox" destination="LLh-vf-2Q3" id="JMi-Mi-Nlx"/>
<outlet property="forgottenFavoritesCheckbox" destination="cGj-g9-2Dm" id="KSf-aG-7Of"/> <outlet property="forgottenFavoritesCheckbox" destination="cGj-g9-2Dm" id="KSf-aG-7Of"/>
<outlet property="forgottenItemLabel" destination="FNU-zj-OIm" id="xkC-K8-zNt"/> <outlet property="forgottenItemLabel" destination="FNU-zj-OIm" id="xkC-K8-zNt"/>
<outlet property="jcMenu" destination="206" id="215"/> <outlet property="jcMenu" destination="206" id="215"/>
<outlet property="mainRecorder" destination="555" id="556"/> <outlet property="mainRecorder" destination="555" id="556"/>
<outlet property="prefsPanel" destination="218" id="220"/> <outlet property="prefsPanel" destination="218" id="220"/>
<outlet property="saveFromBezelToLabel" destination="GRg-nv-Opa" id="hLw-Hb-VQg"/>
<outlet property="saveToLocationButton" destination="Bqn-So-8E9" id="vh2-7q-lE5"/>
<outlet property="savingSectionLabel" destination="g6p-DW-uAA" id="4n5-RC-Ijw"/>
<outlet property="searchBox" destination="BYk-Gn-IDB" id="MpX-C1-cdn"/> <outlet property="searchBox" destination="BYk-Gn-IDB" id="MpX-C1-cdn"/>
</connections> </connections>
</customObject> </customObject>
@ -111,33 +115,31 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES"/> <windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="542" y="303" width="507" height="471"/> <rect key="contentRect" x="542" y="303" width="507" height="471"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/> <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1025"/>
<value key="minSize" type="size" width="213" height="107"/> <value key="minSize" type="size" width="213" height="107"/>
<view key="contentView" id="219"> <view key="contentView" id="219">
<rect key="frame" x="0.0" y="0.0" width="507" height="471"/> <rect key="frame" x="0.0" y="0.0" width="507" height="471"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<tabView fixedFrame="YES" type="noTabsNoBorder" translatesAutoresizingMaskIntoConstraints="NO" id="345"> <tabView fixedFrame="YES" type="noTabsNoBorder" translatesAutoresizingMaskIntoConstraints="NO" id="345">
<rect key="frame" x="0.0" y="0.0" width="507" height="471"/> <rect key="frame" x="0.0" y="0.0" width="507" height="520"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<tabViewItems> <tabViewItems>
<tabViewItem label="General" identifier="net.sf.jumpcut.preferences.general.tiff" id="359"> <tabViewItem label="General" identifier="net.sf.jumpcut.preferences.general.tiff" id="359">
<view key="view" ambiguous="YES" id="360"> <view key="view" id="360">
<rect key="frame" x="0.0" y="0.0" width="507" height="471"/> <rect key="frame" x="0.0" y="0.0" width="507" height="520"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<box fixedFrame="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="387"> <box misplaced="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="387">
<rect key="frame" x="-3" y="136" width="555" height="349"/> <rect key="frame" x="0.0" y="40" width="507" height="520"/>
<autoresizingMask key="autoresizingMask"/> <view key="contentView" id="OKE-OW-DrT">
<view key="contentView" ambiguous="YES" id="OKE-OW-DrT"> <rect key="frame" x="0.0" y="0.0" width="507" height="520"/>
<rect key="frame" x="0.0" y="0.0" width="555" height="349"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<button toolTip="The bezel must be manually dismissed using the &quot;escape&quot; or &quot;return&quot; keys." fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="390"> <button toolTip="The bezel must be manually dismissed using the &quot;escape&quot; or &quot;return&quot; keys." translatesAutoresizingMaskIntoConstraints="NO" id="390">
<rect key="frame" x="14" y="319" width="97" height="18"/> <rect key="frame" x="14" y="487" width="477" height="18"/>
<autoresizingMask key="autoresizingMask"/> <buttonCell key="cell" type="check" title="Sticky bezel (bezel, or pop-up, stays visible after hotkey is released)" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="750">
<buttonCell key="cell" type="check" title="Sticky bezel" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="750">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
</buttonCell> </buttonCell>
@ -145,12 +147,93 @@
<binding destination="808" name="value" keyPath="values.stickyBezel" id="811"/> <binding destination="808" name="value" keyPath="values.stickyBezel" id="811"/>
</connections> </connections>
</button> </button>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="392"> <button toolTip="In the bezel, moving down from the last item takes you to the top and moving up from the first item takes you to the bottom." translatesAutoresizingMaskIntoConstraints="NO" id="692">
<rect key="frame" x="79" y="179" width="189" height="26"/> <rect key="frame" x="14" y="467" width="477" height="18"/>
<autoresizingMask key="autoresizingMask"/> <buttonCell key="cell" type="check" title="Wraparound bezel (the first and last items are adjacent in order)" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="762">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.wraparoundBezel" id="814"/>
</connections>
</button>
<button toolTip="Selecting a clipping from the menu causes it to be pasted instead of copied back onto the pasteboard." translatesAutoresizingMaskIntoConstraints="NO" id="694">
<rect key="frame" x="14" y="447" width="477" height="18"/>
<buttonCell key="cell" type="check" title="Menu selection pastes" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="763">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.menuSelectionPastes" id="817"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="398">
<rect key="frame" x="14" y="427" width="477" height="18"/>
<buttonCell key="cell" type="check" title="Launch Flycut on login" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="753">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleLoadOnStartup:" target="213" id="773"/>
<binding destination="808" name="value" keyPath="values.loadOnStartup" id="820"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oXn-B4-1Ni">
<rect key="frame" x="34" y="408" width="80" height="16"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="iCloud Sync:" id="17g-S0-Mqp">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="bqG-v4-vqw">
<rect key="frame" x="118" y="407" width="77" height="18"/>
<buttonCell key="cell" type="check" title="Settings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="d4T-QV-zqa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleICloudSyncSettings:" target="213" id="lWN-Hi-1aI"/>
<binding destination="808" name="value" keyPath="values.syncSettingsViaICloud" id="q7Y-Id-atI"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="IXN-q7-y5J">
<rect key="frame" x="201" y="407" width="83" height="18"/>
<buttonCell key="cell" type="check" title="Clippings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="oLL-dD-GRW">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleICloudSyncClippings:" target="213" id="hdD-v4-8dV"/>
<binding destination="808" name="value" keyPath="values.syncClippingsViaICloud" id="gbJ-fW-npv"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="416">
<rect key="frame" x="14" y="384" width="479" height="16"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Clippings:" id="754">
<font key="font" metaFont="systemSemibold" size="13"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="1000" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="418">
<rect key="frame" x="14" y="348" width="30" height="28"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="755">
<font key="font" metaFont="label" size="11"/>
<string key="title">Save
</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="392">
<rect key="frame" x="47" y="355" width="189" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="182" id="xgu-QS-ucU"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="On exit" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="394" id="751"> <popUpButtonCell key="cell" type="push" title="On exit" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="394" id="751">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="menu"/>
<menu key="menu" title="OtherViews" id="393"> <menu key="menu" title="OtherViews" id="393">
<items> <items>
<menuItem title="Never" id="395"/> <menuItem title="Never" id="395"/>
@ -164,86 +247,8 @@
<binding destination="808" name="selectedIndex" keyPath="values.savePreference" id="823"/> <binding destination="808" name="selectedIndex" keyPath="values.savePreference" id="823"/>
</connections> </connections>
</popUpButton> </popUpButton>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="398"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="419">
<rect key="frame" x="14" y="259" width="162" height="18"/> <rect key="frame" x="14" y="312" width="61" height="28"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Launch Flycut on login" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="753">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleLoadOnStartup:" target="213" id="773"/>
<binding destination="808" name="value" keyPath="values.loadOnStartup" id="820"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IXN-q7-y5J">
<rect key="frame" x="193" y="239" width="79" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Clippings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="oLL-dD-GRW">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleICloudSyncClippings:" target="213" id="hdD-v4-8dV"/>
<binding destination="808" name="value" keyPath="values.syncClippingsViaICloud" id="gbJ-fW-npv"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="897">
<rect key="frame" x="14" y="123" width="247" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Don't copy from password fields" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="898">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordFields" id="902"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="903">
<rect key="frame" x="14" y="41" width="247" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Remove duplicates" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="904">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.removeDuplicates" id="906"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="416">
<rect key="frame" x="13" y="207" width="76" height="23"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="754">
<font key="font" metaFont="system"/>
<string key="title">Clippings:
</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oXn-B4-1Ni">
<rect key="frame" x="32" y="223" width="116" height="34"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="iCloud Sync:" id="17g-S0-Mqp">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="418">
<rect key="frame" x="13" y="185" width="33" height="14"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="755">
<font key="font" metaFont="label" size="11"/>
<string key="title">Save
</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="419">
<rect key="frame" x="13" y="159" width="62" height="14"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="756"> <textFieldCell key="cell" sendsActionOnEndEditing="YES" id="756">
<font key="font" metaFont="label" size="11"/> <font key="font" metaFont="label" size="11"/>
<string key="title">Remember <string key="title">Remember
@ -252,19 +257,12 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="420"> <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="470">
<rect key="frame" x="134" y="159" width="95" height="14"/> <rect key="frame" x="79" y="326" width="34" height="16"/>
<autoresizingMask key="autoresizingMask"/> <constraints>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Display in menu" id="757"> <constraint firstAttribute="width" constant="30" id="CUk-dH-iV9"/>
<font key="font" metaFont="label" size="11"/> </constraints>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" alignment="right" placeholderString="000" id="758">
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="470">
<rect key="frame" x="79" y="154" width="25" height="22"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" id="758">
<numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator=" " id="483"> <numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator=" " id="483">
<attributedString key="attributedStringForZero"> <attributedString key="attributedStringForZero">
<fragment content="0"/> <fragment content="0"/>
@ -280,10 +278,28 @@
<binding destination="808" name="value" keyPath="values.rememberNum" id="826"/> <binding destination="808" name="value" keyPath="values.rememberNum" id="826"/>
</connections> </connections>
</textField> </textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="471"> <stepper toolTip="Controls how many clippings Flycut stores in its stack" horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="472">
<rect key="frame" x="224" y="154" width="24" height="22"/> <rect key="frame" x="113" y="320" width="19" height="28"/>
<autoresizingMask key="autoresizingMask"/> <stepperCell key="cell" continuous="YES" alignment="left" minValue="10" maxValue="999" doubleValue="10" valueWraps="YES" id="760"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" id="759"> <connections>
<action selector="setRememberNumPref:" target="213" id="485"/>
<binding destination="808" name="value" keyPath="values.rememberNum" id="829"/>
</connections>
</stepper>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="420">
<rect key="frame" x="143" y="326" width="87" height="14"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Display in menu" id="757">
<font key="font" metaFont="label" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="471">
<rect key="frame" x="234" y="326" width="29" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="xtz-2M-8Nx"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" alignment="right" placeholderString="000" id="759">
<numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator=" " id="484"> <numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator=" " id="484">
<attributedString key="attributedStringForZero"> <attributedString key="attributedStringForZero">
<fragment content="0"/> <fragment content="0"/>
@ -299,18 +315,8 @@
<binding destination="808" name="value" keyPath="values.displayNum" id="832"/> <binding destination="808" name="value" keyPath="values.displayNum" id="832"/>
</connections> </connections>
</textField> </textField>
<stepper toolTip="Controls how many clippings Flycut stores in its stack" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="472"> <stepper toolTip="Controls how many clippings Flycut shows in the menu" horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="473">
<rect key="frame" x="104" y="152" width="19" height="27"/> <rect key="frame" x="264" y="320" width="19" height="28"/>
<autoresizingMask key="autoresizingMask"/>
<stepperCell key="cell" continuous="YES" alignment="left" minValue="10" maxValue="99" doubleValue="10" valueWraps="YES" id="760"/>
<connections>
<action selector="setRememberNumPref:" target="213" id="485"/>
<binding destination="808" name="value" keyPath="values.rememberNum" id="829"/>
</connections>
</stepper>
<stepper toolTip="Controls how many clippings Flycut shows in the menu" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="473">
<rect key="frame" x="249" y="152" width="19" height="27"/>
<autoresizingMask key="autoresizingMask"/>
<stepperCell key="cell" continuous="YES" alignment="left" minValue="5" maxValue="99" doubleValue="5" valueWraps="YES" id="761"/> <stepperCell key="cell" continuous="YES" alignment="left" minValue="5" maxValue="99" doubleValue="5" valueWraps="YES" id="761"/>
<connections> <connections>
<action selector="setDisplayNumPref:" target="213" id="486"/> <action selector="setDisplayNumPref:" target="213" id="486"/>
@ -318,63 +324,20 @@
<binding destination="808" name="maxValue" keyPath="values.rememberNum" id="852"/> <binding destination="808" name="maxValue" keyPath="values.rememberNum" id="852"/>
</connections> </connections>
</stepper> </stepper>
<button toolTip="In the bezel, moving down from the last item takes you to the top and moving up from the first item takes you to the bottom." fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="692"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ubt-DS-zHf">
<rect key="frame" x="14" y="299" width="162" height="18"/> <rect key="frame" x="294" y="326" width="52" height="14"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Wraparound bezel" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="762">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.wraparoundBezel" id="814"/>
</connections>
</button>
<button toolTip="Selecting a clipping from the menu causes it to be pasted instead of copied back onto the pasteboard." fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="694">
<rect key="frame" x="14" y="279" width="162" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Menu selection pastes" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="763">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.menuSelectionPastes" id="817"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="914">
<rect key="frame" x="14" y="21" width="230" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Move pasted item to top of stack" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="915">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.pasteMovesToTop" id="922"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LLh-vf-2Q3">
<rect key="frame" x="246" y="1" width="87" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Clippings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="oLu-XL-Wuo">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.saveForgottenClippings" id="9eO-xd-ge5"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ubt-DS-zHf">
<rect key="frame" x="280" y="159" width="62" height="14"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Favorites" id="2L6-OM-5rx"> <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Favorites" id="2L6-OM-5rx">
<font key="font" metaFont="label" size="11"/> <font key="font" metaFont="label" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dM5-eN-Zvt"> <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dM5-eN-Zvt">
<rect key="frame" x="346" y="154" width="25" height="22"/> <rect key="frame" x="350" y="326" width="29" height="16"/>
<autoresizingMask key="autoresizingMask"/> <constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" id="nes-6O-e5R"> <constraint firstAttribute="width" constant="25" id="wV6-2I-Qfq"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" alignment="right" placeholderString="000" id="nes-6O-e5R">
<numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator="," id="aqt-p2-eya"> <numberFormatter key="formatter" formatterBehavior="10_0" positiveFormat="#" negativeFormat="-#" hasThousandSeparators="NO" thousandSeparator="," id="aqt-p2-eya">
<attributedString key="attributedStringForZero"> <attributedString key="attributedStringForZero">
<fragment content="0"/> <fragment content="0"/>
@ -387,21 +350,37 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
<connections> <connections>
<binding destination="808" name="value" keyPath="values.rememberNum" id="887-jS-Kpn"/> <binding destination="808" name="value" keyPath="values.favoritesRememberNum" id="bQe-4R-RSr"/>
</connections> </connections>
</textField> </textField>
<stepper toolTip="Controls how many clippings Flycut stores in its stack" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wZv-HJ-VdW"> <stepper toolTip="Controls how many clippings Flycut stores in its favorites stack" horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wZv-HJ-VdW">
<rect key="frame" x="371" y="152" width="19" height="27"/> <rect key="frame" x="380" y="320" width="19" height="28"/>
<autoresizingMask key="autoresizingMask"/> <stepperCell key="cell" continuous="YES" alignment="left" minValue="10" maxValue="999" doubleValue="10" valueWraps="YES" id="gUi-gl-RH6"/>
<stepperCell key="cell" continuous="YES" alignment="left" minValue="10" maxValue="99" doubleValue="10" valueWraps="YES" id="gUi-gl-RH6"/>
<connections> <connections>
<action selector="setFavoritesRememberNumPref:" target="213" id="rm7-TX-1af"/> <action selector="setFavoritesRememberNumPref:" target="213" id="rm7-TX-1af"/>
<binding destination="808" name="value" keyPath="values.rememberNum" id="nUm-81-DgP"/> <binding destination="808" name="value" keyPath="values.favoritesRememberNum" id="nUm-81-DgP"/>
</connections> </connections>
</stepper> </stepper>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pDS-jE-9jb"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IZZ-Ep-7nD" userLabel="Passwords:">
<rect key="frame" x="32" y="103" width="133" height="18"/> <rect key="frame" x="14" y="288" width="479" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Passwords:" id="cLX-o3-ZMz">
<font key="font" metaFont="systemSemibold" size="13"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="897">
<rect key="frame" x="14" y="263" width="477" height="18"/>
<buttonCell key="cell" type="check" title="Don't copy from password fields" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="898">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordFields" id="902"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="pDS-jE-9jb">
<rect key="frame" x="34" y="243" width="136" height="18"/>
<buttonCell key="cell" type="check" title="Pasteboard types:" bezelStyle="regularSquare" imagePosition="left" inset="2" id="tzh-NM-RSb"> <buttonCell key="cell" type="check" title="Pasteboard types:" bezelStyle="regularSquare" imagePosition="left" inset="2" id="tzh-NM-RSb">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -410,43 +389,8 @@
<binding destination="808" name="value" keyPath="values.skipPboardTypes" id="kfD-fG-t1V"/> <binding destination="808" name="value" keyPath="values.skipPboardTypes" id="kfD-fG-t1V"/>
</connections> </connections>
</button> </button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Bxp-pI-XMk"> <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="x34-dK-wxl">
<rect key="frame" x="32" y="82" width="356" height="18"/> <rect key="frame" x="178" y="242" width="313" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Detect with Upper, Lower, Digit, and Symbol lengths:" bezelStyle="regularSquare" imagePosition="left" inset="2" id="aAK-L0-EHa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordLengths" id="PyJ-gO-ieM"/>
</connections>
</button>
<button toolTip="For identifying types to include in Pasteboard Types above." fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mka-NZ-Esg">
<rect key="frame" x="32" y="62" width="279" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Include pasteboard types in clippings list" bezelStyle="regularSquare" imagePosition="left" inset="2" id="9Vi-RY-G0b">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.revealPasteboardTypes" id="Nn3-7D-D7e"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RYj-wx-tTx">
<rect key="frame" x="394" y="80" width="108" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="12, 20, 32" drawsBackground="YES" id="aqQ-SR-BmT">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordLengthsList" id="NJg-wN-gsn"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="x34-dK-wxl">
<rect key="frame" x="171" y="101" width="331" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="PasswordPboardType" drawsBackground="YES" id="kTZ-dC-s1q"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="PasswordPboardType" drawsBackground="YES" id="kTZ-dC-s1q">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -456,18 +400,121 @@
<binding destination="808" name="value" keyPath="values.skipPboardTypesList" id="Wbn-u9-3vY"/> <binding destination="808" name="value" keyPath="values.skipPboardTypesList" id="Wbn-u9-3vY"/>
</connections> </connections>
</textField> </textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FNU-zj-OIm"> <button translatesAutoresizingMaskIntoConstraints="NO" id="Bxp-pI-XMk">
<rect key="frame" x="32" y="2" width="211" height="17"/> <rect key="frame" x="34" y="223" width="345" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <buttonCell key="cell" type="check" title="Detect with Upper, Lower, Digit, and Symbol lengths:" bezelStyle="regularSquare" imagePosition="left" inset="2" id="aAK-L0-EHa">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Save forgotten items to Desktop:" id="ksy-al-FbE"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordLengths" id="PyJ-gO-ieM"/>
</connections>
</button>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RYj-wx-tTx">
<rect key="frame" x="387" y="222" width="104" height="21"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="12, 20, 32" drawsBackground="YES" id="aqQ-SR-BmT">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="808" name="value" keyPath="values.skipPasswordLengthsList" id="NJg-wN-gsn"/>
</connections>
</textField>
<button toolTip="For identifying types to include in Pasteboard Types above." translatesAutoresizingMaskIntoConstraints="NO" id="mka-NZ-Esg">
<rect key="frame" x="34" y="203" width="274" height="18"/>
<buttonCell key="cell" type="check" title="Include pasteboard types in clippings list" bezelStyle="regularSquare" imagePosition="left" inset="2" id="9Vi-RY-G0b">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.revealPasteboardTypes" id="Nn3-7D-D7e"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Y84-Ix-WCR" userLabel="Organizing:">
<rect key="frame" x="14" y="180" width="479" height="16"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Organizing:" id="3tC-1z-0C9">
<font key="font" metaFont="systemSemibold" size="13"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="903">
<rect key="frame" x="14" y="155" width="477" height="18"/>
<buttonCell key="cell" type="check" title="Remove duplicates" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="904">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.removeDuplicates" id="906"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="914">
<rect key="frame" x="14" y="135" width="477" height="18"/>
<buttonCell key="cell" type="check" title="Move pasted item to top of stack" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="915">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.pasteMovesToTop" id="922"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="g6p-DW-uAA" userLabel="Saving:">
<rect key="frame" x="14" y="112" width="479" height="16"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Saving:" id="bsj-XZ-XVF">
<font key="font" metaFont="systemSemibold" size="13"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GRg-nv-Opa" userLabel="Save from bezel to:">
<rect key="frame" x="14" y="88" width="121" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Save from bezel to:" id="5L1-9C-Fdd">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cGj-g9-2Dm"> <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Bqn-So-8E9" userLabel="SaveToButton">
<rect key="frame" x="337" y="1" width="157" height="18"/> <rect key="frame" x="134" y="79" width="85" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <buttonCell key="cell" type="push" title="Desktop" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Ldc-9D-vz1">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="selectSaveLocation:" target="213" id="wgc-Dj-9ke"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FNU-zj-OIm">
<rect key="frame" x="14" y="64" width="149" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Save forgotten items to:" id="ksy-al-FbE">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="PJD-Fc-76A" userLabel="AutoSaveToButton">
<rect key="frame" x="162" y="55" width="85" height="32"/>
<buttonCell key="cell" type="push" title="Desktop" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="K2A-qx-BB8">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="selectSaveLocation:" target="213" id="T8h-Ac-NLL"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="LLh-vf-2Q3">
<rect key="frame" x="246" y="63" width="83" height="18"/>
<buttonCell key="cell" type="check" title="Clippings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="oLu-XL-Wuo">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="808" name="value" keyPath="values.saveForgottenClippings" id="9eO-xd-ge5"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="cGj-g9-2Dm">
<rect key="frame" x="335" y="63" width="81" height="18"/>
<buttonCell key="cell" type="check" title="Favorites" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="vC2-Ch-UPQ"> <buttonCell key="cell" type="check" title="Favorites" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="vC2-Ch-UPQ">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -476,33 +523,120 @@
<binding destination="808" name="value" keyPath="values.saveForgottenFavorites" id="WTf-Ip-R9L"/> <binding destination="808" name="value" keyPath="values.saveForgottenFavorites" id="WTf-Ip-R9L"/>
</connections> </connections>
</button> </button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bqG-v4-vqw">
<rect key="frame" x="116" y="239" width="73" height="18"/>
<autoresizingMask key="autoresizingMask"/>
<buttonCell key="cell" type="check" title="Settings" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="d4T-QV-zqa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleICloudSyncSettings:" target="213" id="lWN-Hi-1aI"/>
<binding destination="808" name="value" keyPath="values.syncSettingsViaICloud" id="q7Y-Id-atI"/>
</connections>
</button>
</subviews> </subviews>
<constraints>
<constraint firstItem="419" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="0OA-ei-ed9"/>
<constraint firstItem="IZZ-Ep-7nD" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="1Yq-Ci-o9Y"/>
<constraint firstItem="897" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="2EU-FY-QhB"/>
<constraint firstItem="470" firstAttribute="leading" secondItem="419" secondAttribute="trailing" constant="8" symbolic="YES" id="2SS-tf-dnl"/>
<constraint firstItem="x34-dK-wxl" firstAttribute="leading" secondItem="pDS-jE-9jb" secondAttribute="trailing" constant="8" id="2oa-Ko-tPw"/>
<constraint firstItem="390" firstAttribute="top" secondItem="OKE-OW-DrT" secondAttribute="top" constant="16" id="3WW-PL-oMV"/>
<constraint firstItem="390" firstAttribute="leading" secondItem="OKE-OW-DrT" secondAttribute="leading" constant="16" id="4AU-hf-tHV"/>
<constraint firstItem="Bqn-So-8E9" firstAttribute="leading" secondItem="GRg-nv-Opa" secondAttribute="trailing" constant="8" id="4Yw-Fu-mY5"/>
<constraint firstItem="IZZ-Ep-7nD" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="58a-TR-ref"/>
<constraint firstItem="x34-dK-wxl" firstAttribute="centerY" secondItem="pDS-jE-9jb" secondAttribute="centerY" id="5gD-Jm-AWK"/>
<constraint firstAttribute="trailing" secondItem="x34-dK-wxl" secondAttribute="trailing" constant="16" id="63n-I3-kLa"/>
<constraint firstItem="GRg-nv-Opa" firstAttribute="top" secondItem="g6p-DW-uAA" secondAttribute="bottom" constant="8" id="63n-kR-a6q"/>
<constraint firstItem="903" firstAttribute="top" secondItem="Y84-Ix-WCR" secondAttribute="bottom" constant="8" id="85d-e5-tMQ"/>
<constraint firstItem="419" firstAttribute="top" secondItem="418" secondAttribute="bottom" constant="8" id="8QQ-I9-aMj"/>
<constraint firstItem="Y84-Ix-WCR" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="8n3-Fh-HPU"/>
<constraint firstItem="470" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="9I5-Oh-rPd"/>
<constraint firstItem="Bqn-So-8E9" firstAttribute="centerY" secondItem="GRg-nv-Opa" secondAttribute="centerY" id="AFQ-dB-abo"/>
<constraint firstItem="398" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="BAI-dH-bSv"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="FNU-zj-OIm" secondAttribute="bottom" constant="16" id="Bgo-q3-Evl"/>
<constraint firstItem="416" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="BxJ-J8-n2m"/>
<constraint firstAttribute="trailing" secondItem="RYj-wx-tTx" secondAttribute="trailing" constant="16" id="C8f-Q9-F5O"/>
<constraint firstItem="903" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="CEg-IE-Ros"/>
<constraint firstItem="dM5-eN-Zvt" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="CW3-B2-Nke"/>
<constraint firstItem="416" firstAttribute="top" secondItem="oXn-B4-1Ni" secondAttribute="bottom" constant="8" id="F4X-cP-nBC"/>
<constraint firstItem="FNU-zj-OIm" firstAttribute="centerY" secondItem="PJD-Fc-76A" secondAttribute="centerY" id="GLR-pi-A9f"/>
<constraint firstItem="pDS-jE-9jb" firstAttribute="leading" secondItem="897" secondAttribute="leading" constant="20" id="GYo-j6-3vw"/>
<constraint firstItem="398" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="Ggu-1n-f2v"/>
<constraint firstItem="914" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="HgF-tD-X6T"/>
<constraint firstItem="Bxp-pI-XMk" firstAttribute="top" secondItem="pDS-jE-9jb" secondAttribute="bottom" constant="4" id="IB8-Wb-AWb"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="cGj-g9-2Dm" secondAttribute="trailing" constant="16" id="IO6-sz-Wmo"/>
<constraint firstItem="mka-NZ-Esg" firstAttribute="top" secondItem="Bxp-pI-XMk" secondAttribute="bottom" constant="4" id="LMp-eg-a6v"/>
<constraint firstItem="398" firstAttribute="top" secondItem="694" secondAttribute="bottom" constant="4" id="LYa-Bc-sCv"/>
<constraint firstItem="oXn-B4-1Ni" firstAttribute="leading" secondItem="398" secondAttribute="leading" constant="20" id="LiX-K9-GGv"/>
<constraint firstItem="694" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="MBb-5l-ePl"/>
<constraint firstItem="dM5-eN-Zvt" firstAttribute="leading" secondItem="Ubt-DS-zHf" secondAttribute="trailing" constant="8" symbolic="YES" id="NXg-qx-3RD"/>
<constraint firstItem="392" firstAttribute="firstBaseline" secondItem="418" secondAttribute="firstBaseline" id="NYT-Ws-Grq"/>
<constraint firstItem="LLh-vf-2Q3" firstAttribute="centerY" secondItem="FNU-zj-OIm" secondAttribute="centerY" id="OCy-GX-PhU"/>
<constraint firstItem="897" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="OOV-o3-Kqw"/>
<constraint firstItem="IXN-q7-y5J" firstAttribute="leading" secondItem="bqG-v4-vqw" secondAttribute="trailing" constant="8" id="OWr-XG-nOi"/>
<constraint firstItem="cGj-g9-2Dm" firstAttribute="leading" secondItem="LLh-vf-2Q3" secondAttribute="trailing" constant="8" id="OiD-MJ-3oZ"/>
<constraint firstItem="bqG-v4-vqw" firstAttribute="leading" secondItem="oXn-B4-1Ni" secondAttribute="trailing" constant="8" id="Pnm-sg-o01"/>
<constraint firstItem="PJD-Fc-76A" firstAttribute="leading" secondItem="FNU-zj-OIm" secondAttribute="trailing" constant="8" id="QQj-Rc-WHS"/>
<constraint firstItem="694" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="QjU-Yy-d2y"/>
<constraint firstItem="cGj-g9-2Dm" firstAttribute="centerY" secondItem="FNU-zj-OIm" secondAttribute="centerY" id="UXg-nV-5uk"/>
<constraint firstItem="418" firstAttribute="top" secondItem="416" secondAttribute="bottom" constant="8" id="VNz-aL-KCx"/>
<constraint firstItem="473" firstAttribute="leading" secondItem="471" secondAttribute="trailing" constant="6" id="VdT-8E-s3R"/>
<constraint firstItem="Bqn-So-8E9" firstAttribute="trailing" relation="lessThanOrEqual" secondItem="390" secondAttribute="trailing" id="VeU-DE-gRe"/>
<constraint firstItem="Y84-Ix-WCR" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="WHB-9p-hWJ"/>
<constraint firstItem="wZv-HJ-VdW" firstAttribute="leading" secondItem="dM5-eN-Zvt" secondAttribute="trailing" constant="6" id="WrE-NL-zxb"/>
<constraint firstItem="420" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="X0m-LH-JXU"/>
<constraint firstItem="Bxp-pI-XMk" firstAttribute="leading" secondItem="897" secondAttribute="leading" constant="20" id="XCO-Pl-Mxm"/>
<constraint firstItem="471" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="XmO-SK-wbg"/>
<constraint firstItem="LLh-vf-2Q3" firstAttribute="leading" secondItem="PJD-Fc-76A" secondAttribute="trailing" constant="8" id="ZkB-0I-uW3"/>
<constraint firstItem="g6p-DW-uAA" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="aJn-m2-qIb"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="wZv-HJ-VdW" secondAttribute="trailing" constant="16" id="bAa-Y7-Ufp"/>
<constraint firstItem="897" firstAttribute="top" secondItem="IZZ-Ep-7nD" secondAttribute="bottom" constant="8" id="bWw-xW-3pk"/>
<constraint firstItem="Ubt-DS-zHf" firstAttribute="leading" secondItem="473" secondAttribute="trailing" constant="16" id="bq9-zJ-hAm"/>
<constraint firstItem="pDS-jE-9jb" firstAttribute="top" secondItem="897" secondAttribute="bottom" constant="4" id="bzC-5n-599"/>
<constraint firstItem="g6p-DW-uAA" firstAttribute="top" secondItem="914" secondAttribute="bottom" constant="8" id="c0s-2l-T8Z"/>
<constraint firstItem="GRg-nv-Opa" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="cgO-SI-hPU"/>
<constraint firstItem="wZv-HJ-VdW" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="crp-Nh-USz"/>
<constraint firstItem="914" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="dnB-pc-kVq"/>
<constraint firstItem="471" firstAttribute="leading" secondItem="420" secondAttribute="trailing" constant="8" symbolic="YES" id="dpK-2h-xHg"/>
<constraint firstItem="Ubt-DS-zHf" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="ea2-3T-gv7"/>
<constraint firstItem="472" firstAttribute="leading" secondItem="470" secondAttribute="trailing" constant="5" id="em0-Uc-eQr"/>
<constraint firstItem="418" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="gzd-Qn-vkn"/>
<constraint firstItem="420" firstAttribute="leading" secondItem="472" secondAttribute="trailing" constant="16" id="ish-En-B66"/>
<constraint firstItem="692" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="jLX-6E-xU8"/>
<constraint firstItem="IXN-q7-y5J" firstAttribute="centerY" secondItem="oXn-B4-1Ni" secondAttribute="centerY" id="jrR-OL-dfq"/>
<constraint firstItem="472" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="k8D-eK-Lkg"/>
<constraint firstItem="mka-NZ-Esg" firstAttribute="leading" secondItem="897" secondAttribute="leading" constant="20" id="kqa-hO-Tgb"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="IXN-q7-y5J" secondAttribute="trailing" constant="16" id="lnR-NY-f9w"/>
<constraint firstItem="903" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="mcA-EQ-hXJ"/>
<constraint firstItem="692" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="nT0-7c-Qau"/>
<constraint firstItem="FNU-zj-OIm" firstAttribute="top" secondItem="GRg-nv-Opa" secondAttribute="bottom" constant="8" id="p6b-hb-TkQ"/>
<constraint firstItem="392" firstAttribute="leading" secondItem="418" secondAttribute="trailing" constant="8" id="qNy-dd-GTI"/>
<constraint firstItem="694" firstAttribute="top" secondItem="692" secondAttribute="bottom" constant="4" id="qVT-TM-MxF"/>
<constraint firstItem="Y84-Ix-WCR" firstAttribute="top" secondItem="mka-NZ-Esg" secondAttribute="bottom" constant="8" id="qcI-Ml-osE"/>
<constraint firstItem="oXn-B4-1Ni" firstAttribute="top" secondItem="398" secondAttribute="bottom" constant="4" id="rLY-8f-Ddg"/>
<constraint firstItem="RYj-wx-tTx" firstAttribute="centerY" secondItem="Bxp-pI-XMk" secondAttribute="centerY" id="t66-fT-3SX"/>
<constraint firstAttribute="trailing" secondItem="390" secondAttribute="trailing" constant="16" id="ti1-k0-aLE"/>
<constraint firstItem="RYj-wx-tTx" firstAttribute="leading" secondItem="Bxp-pI-XMk" secondAttribute="trailing" constant="8" id="uer-Iu-d76"/>
<constraint firstItem="g6p-DW-uAA" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="v9C-kf-Qoy"/>
<constraint firstItem="416" firstAttribute="trailing" secondItem="390" secondAttribute="trailing" id="vN9-3Q-dlX"/>
<constraint firstItem="914" firstAttribute="top" secondItem="903" secondAttribute="bottom" constant="4" id="vUJ-m6-h6j"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="392" secondAttribute="trailing" constant="16" id="w0m-0A-rhs"/>
<constraint firstItem="bqG-v4-vqw" firstAttribute="centerY" secondItem="oXn-B4-1Ni" secondAttribute="centerY" id="xqP-UF-xeE"/>
<constraint firstItem="473" firstAttribute="firstBaseline" secondItem="419" secondAttribute="firstBaseline" id="yKX-vf-1GN"/>
<constraint firstItem="FNU-zj-OIm" firstAttribute="leading" secondItem="390" secondAttribute="leading" id="yqk-DD-uql"/>
<constraint firstItem="692" firstAttribute="top" secondItem="390" secondAttribute="bottom" constant="4" id="yvi-Jb-7If"/>
<constraint firstItem="IZZ-Ep-7nD" firstAttribute="top" secondItem="419" secondAttribute="bottom" constant="8" id="ztE-db-uZr"/>
</constraints>
</view> </view>
</box> </box>
</subviews> </subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="387" secondAttribute="trailing" id="1tp-B7-zu0"/>
<constraint firstItem="387" firstAttribute="top" secondItem="360" secondAttribute="top" id="nuT-kv-kuD"/>
<constraint firstItem="387" firstAttribute="leading" secondItem="360" secondAttribute="leading" id="zUp-0A-XJv"/>
<constraint firstAttribute="bottom" secondItem="387" secondAttribute="bottom" id="zmW-H9-0um"/>
</constraints>
</view> </view>
</tabViewItem> </tabViewItem>
<tabViewItem label="Hotkeys" identifier="net.sf.jumpcut.preferences.hotkey.tiff" id="346"> <tabViewItem label="Hotkeys" identifier="net.sf.jumpcut.preferences.hotkey.tiff" id="346">
<view key="view" id="347"> <view key="view" id="347">
<rect key="frame" x="0.0" y="0.0" width="507" height="471"/> <rect key="frame" x="0.0" y="0.0" width="507" height="520"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<box fixedFrame="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="348"> <box fixedFrame="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="348">
<rect key="frame" x="0.0" y="227" width="555" height="125"/> <rect key="frame" x="0.0" y="227" width="555" height="125"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" ambiguous="YES" id="Kdy-dK-U26"> <view key="contentView" id="Kdy-dK-U26">
<rect key="frame" x="0.0" y="0.0" width="555" height="125"/> <rect key="frame" x="0.0" y="0.0" width="555" height="125"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
@ -564,18 +698,18 @@
<box fixedFrame="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="354"> <box fixedFrame="YES" boxType="oldStyle" borderType="none" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="354">
<rect key="frame" x="-3" y="109" width="555" height="376"/> <rect key="frame" x="-3" y="109" width="555" height="376"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" ambiguous="YES" id="Rzy-Jv-79m"> <view key="contentView" id="Rzy-Jv-79m">
<rect key="frame" x="0.0" y="0.0" width="555" height="376"/> <rect key="frame" x="0.0" y="0.0" width="555" height="376"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<scrollView fixedFrame="YES" horizontalLineScroll="0.0" horizontalPageScroll="0.0" verticalLineScroll="0.0" verticalPageScroll="0.0" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="356"> <scrollView fixedFrame="YES" horizontalLineScroll="0.0" horizontalPageScroll="0.0" verticalLineScroll="0.0" verticalPageScroll="0.0" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="356">
<rect key="frame" x="16" y="16" width="476" height="346"/> <rect key="frame" x="16" y="16" width="476" height="346"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="Yuw-af-7PF"> <clipView key="contentView" drawsBackground="NO" id="Yuw-af-7PF">
<rect key="frame" x="1" y="1" width="474" height="344"/> <rect key="frame" x="1" y="1" width="474" height="344"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<textView ambiguous="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" usesRuler="YES" spellingCorrection="YES" smartInsertDelete="YES" id="357"> <textView editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" usesRuler="YES" spellingCorrection="YES" smartInsertDelete="YES" id="357">
<rect key="frame" x="0.0" y="0.0" width="474" height="344"/> <rect key="frame" x="0.0" y="0.0" width="474" height="344"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -586,7 +720,7 @@
<fragment content="This text is loaded from acknowledgements.txt"> <fragment content="This text is loaded from acknowledgements.txt">
<attributes> <attributes>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/> <color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" metaFont="user"/> <font key="NSFont" usesAppearanceFont="YES"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural"/> <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
</attributes> </attributes>
</fragment> </fragment>
@ -640,7 +774,7 @@
</connections> </connections>
</searchField> </searchField>
</subviews> </subviews>
<point key="canvasLocation" x="194" y="396"/> <point key="canvasLocation" x="457" y="209"/>
</customView> </customView>
</objects> </objects>
</document> </document>

Binary file not shown.

Binary file not shown.

View file

@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
var window: UIWindow? var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch. // Override point for customization after application launch.
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current() let center = UNUserNotificationCenter.current()

View file

@ -15,7 +15,7 @@ class SettingsViewController: IASKAppSettingsViewController {
} }
// - (id)initWithStyle:(UITableViewStyle)style { // - (id)initWithStyle:(UITableViewStyle)style {
required override init(style:UITableViewStyle) { required override init(style:UITableView.Style) {
super.init(style: style) super.init(style: style)
commonInitContent() commonInitContent()
} }

View file

@ -13,7 +13,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
let flycut:FlycutOperator = FlycutOperator() let flycut:FlycutOperator = FlycutOperator()
var activeUpdates:Int = 0 var activeUpdates:Int = 0
var tableView:UITableView! var tableView:UITableView!
var currentAnimation = UITableViewRowAnimation.none var currentAnimation = UITableView.RowAnimation.none
var pbCount:Int = -1 var pbCount:Int = -1
var rememberedSyncSettings:Bool = false var rememberedSyncSettings:Bool = false
var rememberedSyncClippings:Bool = false var rememberedSyncClippings:Bool = false
@ -60,7 +60,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
let indexPath = self.tableView.indexPath(for: cell) let indexPath = self.tableView.indexPath(for: cell)
if ( nil != indexPath ) { if ( nil != indexPath ) {
let previousAnimation = self.currentAnimation let previousAnimation = self.currentAnimation
self.currentAnimation = UITableViewRowAnimation.left // Use .left to look better with swiping left to delete. self.currentAnimation = UITableView.RowAnimation.left // Use .left to look better with swiping left to delete.
self.flycut.setStackPositionTo( Int32((indexPath?.row)! )) self.flycut.setStackPositionTo( Int32((indexPath?.row)! ))
self.flycut.clearItemAtStackPosition() self.flycut.clearItemAtStackPosition()
self.currentAnimation = previousAnimation self.currentAnimation = previousAnimation
@ -79,7 +79,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
// Fallback on earlier versions // Fallback on earlier versions
UIApplication.shared.openURL(url!) UIApplication.shared.openURL(url!)
} }
self.tableView.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.none) self.tableView.reloadRows(at: [indexPath!], with: UITableView.RowAnimation.none)
} }
return true; return true;
@ -100,18 +100,18 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
flycut.awake(fromNibDisplaying: 10, withDisplayLength: 140, withSave: #selector(savePreferences(toDict:)), forTarget: self) // The 10 isn't used in iOS right now and 140 characters seems to be enough to cover the width of the largest screen. flycut.awake(fromNibDisplaying: 10, withDisplayLength: 140, withSave: #selector(savePreferences(toDict:)), forTarget: self) // The 10 isn't used in iOS right now and 140 characters seems to be enough to cover the width of the largest screen.
NotificationCenter.default.addObserver(self, selector: #selector(self.checkForClippingAddedToClipboard), name: .UIPasteboardChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.checkForClippingAddedToClipboard), name: UIPasteboard.changedNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.applicationWillTerminate), name: .UIApplicationWillTerminate, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.applicationWillTerminate), name: UIApplication.willTerminateNotification, object: nil)
// Check for clipping whenever we become active. // Check for clipping whenever we become active.
NotificationCenter.default.addObserver(self, selector: #selector(self.checkForClippingAddedToClipboard), name: .UIApplicationDidBecomeActive, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.checkForClippingAddedToClipboard), name: UIApplication.didBecomeActiveNotification, object: nil)
checkForClippingAddedToClipboard() // Since the first-launch notification will occur before we add observer. checkForClippingAddedToClipboard() // Since the first-launch notification will occur before we add observer.
// Register for notifications for the scenarios in which we should save the engine. // Register for notifications for the scenarios in which we should save the engine.
[ Notification.Name.UIApplicationWillResignActive, [ UIApplication.willResignActiveNotification,
Notification.Name.UIApplicationDidEnterBackground, UIApplication.didEnterBackgroundNotification,
Notification.Name.UIApplicationWillTerminate ] UIApplication.willTerminateNotification ]
.forEach { (notification) in .forEach { (notification) in
NotificationCenter.default.addObserver(self, NotificationCenter.default.addObserver(self,
selector: #selector(self.saveEngine), selector: #selector(self.saveEngine),
@ -148,7 +148,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
} }
} }
func defaultsChanged() { @objc func defaultsChanged() {
// This seems to be the only way to respond to Settings changes, though it doesn't inform us what changed so we will have to check each to see if they were the one(s). // This seems to be the only way to respond to Settings changes, though it doesn't inform us what changed so we will have to check each to see if they were the one(s).
// Don't use DispatchQueue.main.async since that will still end up blocking the UI draw until the user responds to what hasn't been drawn yet. // Don't use DispatchQueue.main.async since that will still end up blocking the UI draw until the user responds to what hasn't been drawn yet.
@ -209,7 +209,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
flycut.willShowPreferences() flycut.willShowPreferences()
} }
func savePreferences(toDict: NSMutableDictionary) @objc func savePreferences(toDict: NSMutableDictionary)
{ {
} }
@ -320,7 +320,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
return selection return selection
} }
func checkForClippingAddedToClipboard() @objc func checkForClippingAddedToClipboard()
{ {
pasteboardInteractionQueue.async { pasteboardInteractionQueue.async {
// This is a suitable place to prepare to possible eventual display of preferences, resetting values that should reset before each display of preferences. // This is a suitable place to prepare to possible eventual display of preferences, resetting values that should reset before each display of preferences.
@ -330,26 +330,26 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
{ {
self.pbCount = UIPasteboard.general.changeCount; self.pbCount = UIPasteboard.general.changeCount;
if ( UIPasteboard.general.types.contains("public.utf8-plain-text") ) if UIPasteboard.general.types.contains("public.utf8-plain-text"),
let pasteboard = UIPasteboard.general.value(forPasteboardType: "public.utf8-plain-text") as? String
{ {
let pasteboard = UIPasteboard.general.value(forPasteboardType: "public.utf8-plain-text") self.flycut.addClipping(pasteboard, ofType: "public.utf8-plain-text", fromApp: "iOS", withAppBundleURL: "iOS", target: nil, clippingAddedSelector: nil)
self.flycut.addClipping(pasteboard as! String!, ofType: "public.utf8-plain-text", fromApp: "iOS", withAppBundleURL: "iOS", target: nil, clippingAddedSelector: nil)
} }
else if ( UIPasteboard.general.types.contains("public.text") ) else if UIPasteboard.general.types.contains("public.text"),
let pasteboard = UIPasteboard.general.value(forPasteboardType: "public.text") as? String
{ {
let pasteboard = UIPasteboard.general.value(forPasteboardType: "public.text") self.flycut.addClipping(pasteboard, ofType: "public.text", fromApp: "iOS", withAppBundleURL: "iOS", target: nil, clippingAddedSelector: nil)
self.flycut.addClipping(pasteboard as! String!, ofType: "public.text", fromApp: "iOS", withAppBundleURL: "iOS", target: nil, clippingAddedSelector: nil)
} }
} }
} }
} }
func applicationWillTerminate() @objc func applicationWillTerminate()
{ {
saveEngine() saveEngine()
} }
func saveEngine() @objc func saveEngine()
{ {
flycut.saveEngine() flycut.saveEngine()
} }
@ -371,7 +371,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item: MGSwipeTableCell = tableView.dequeueReusableCell(withIdentifier: "FlycutCell", for: indexPath) as! MGSwipeTableCell let item: MGSwipeTableCell = tableView.dequeueReusableCell(withIdentifier: "FlycutCell", for: indexPath) as! MGSwipeTableCell
item.textLabel?.text = flycut.previousDisplayStrings(indexPath.row + 1, containing: nil).last as! String? item.textLabel?.text = flycut.previousDisplayStrings(Int32(indexPath.row + 1), containing: nil).last as! String?
//configure left buttons //configure left buttons
var removeAll:Bool = true var removeAll:Bool = true
@ -382,7 +382,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
// NSTextCheckingResult.CheckingType.link.rawValue blocks things like single words that URL() would let in // NSTextCheckingResult.CheckingType.link.rawValue blocks things like single words that URL() would let in
// URL() blocks things like paragraphs of text containing a URL that NSTextCheckingResult.CheckingType.link.rawValue would let in // URL() blocks things like paragraphs of text containing a URL that NSTextCheckingResult.CheckingType.link.rawValue would let in
let matches = isURLDetector?.matches(in: content, options: .reportCompletion, range: NSMakeRange(0, content.characters.count)) let matches = isURLDetector?.matches(in: content, options: .reportCompletion, range: NSMakeRange(0, content.count))
if let matchesCount = matches?.count if let matchesCount = matches?.count
{ {
if matchesCount > 0 if matchesCount > 0
@ -445,8 +445,9 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
} }
func notifyCKAccountStatusNoAccount() { func notifyCKAccountStatusNoAccount() {
if ( !ignoreCKAccountStatusNoAccount ) DispatchQueue.main.async {
{ guard !self.ignoreCKAccountStatusNoAccount else { return }
let alert = UIAlertController(title: "No iCloud Account", message: "An iCloud account with iCloud Drive enabled is required for iCloud sync.", preferredStyle: .alert) let alert = UIAlertController(title: "No iCloud Account", message: "An iCloud account with iCloud Drive enabled is required for iCloud sync.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Preferences", style: .default, handler: { (_) in alert.addAction(UIAlertAction(title: "Preferences", style: .default, handler: { (_) in
if #available(iOS 10.0, *) if #available(iOS 10.0, *)

View file

@ -4,6 +4,8 @@
#ifdef __OBJC__ #ifdef __OBJC__
#define kiCloudId @"iCloud.com.mark-a-jerde.Flycut"
#ifdef DEBUG #ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); # define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else #else

View file

@ -14,5 +14,7 @@
</array> </array>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict> </dict>
</plist> </plist>

View file

@ -779,6 +779,7 @@
8D1107290486CEB800E47090 /* Resources */, 8D1107290486CEB800E47090 /* Resources */,
8D11072C0486CEB800E47090 /* Sources */, 8D11072C0486CEB800E47090 /* Sources */,
8D11072E0486CEB800E47090 /* Frameworks */, 8D11072E0486CEB800E47090 /* Frameworks */,
8D60A1BA1BC8399900A26CBF /* Set meaningful build number */,
AAE2036C0A27B2B9002DCC2A /* Headers */, AAE2036C0A27B2B9002DCC2A /* Headers */,
77AE730823D2D49100F6A44B /* Embed Frameworks */, 77AE730823D2D49100F6A44B /* Embed Frameworks */,
77192A3923D6F45F00EDB9BC /* CopyFiles */, 77192A3923D6F45F00EDB9BC /* CopyFiles */,
@ -1013,6 +1014,24 @@
}; };
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
8D60A1BA1BC8399900A26CBF /* Set meaningful build number */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;
files = (
);
inputPaths = (
$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH,
);
name = "Set meaningful build number";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Sets the build number to identify, to some extent, the git version of the code.\n# Combines the hash of the origin commit, number of commits of divergence, local HEAD commit, local uncommitted lines of change, and year/month of build.\n# Eliminates all except for the origin commit if there are no local changes, since that can be easily tracked.\n# e.g. 1.b690b47.1.1.cb73ce6.35.1510 from origin b690b47, one and one different, locally at commit cb73ce6, with a further 35 lines of change, built in 2015 in the tenth month. Day numbers are excluded for brevity, as there is already much uncertainty in the local changes and this field is only to indicate a rough level of freshness. Build numer starts with \"1.\" to avoid strange compile errors.\ncd \"${SOURCE_ROOT}\"\n\n# Skip setting the build number if this is a SANDBOXING build, since the helper probably needs a matching build number. Making them match is as easy as putting this script in both targets, though it's also easy to have one target read it from the other, but that's a task best left to the developer doing SANDBOXING builds since they would be in the position to make sure it is done correctly.\ngrep -q '^#define SANDBOXING *$' Flycut_Prefix.pch\nif [ \"0\" != \"$?\" ]\nthen\n\t\n\tORIGIN=$(git rev-parse --short remotes/origin/master)\n\tOFFSET=\".$(git status|sed -n '1,/^# *$/ p'|grep \"[0-9]\"|head -1|sed 's/^[^0-9]*//;s/[^0-9]*$//'|sed 's/[^0-9][^0-9]*/./')\"\n\tLOCAL=\".$(git rev-parse --short HEAD)\"\n\tUNCOMMITTED=\".$(git diff -b -w HEAD|grep \"^[+\\-]\"|grep -v \"^[+\\-][+\\-][+\\-] [ab]\"|wc -l|sed 's/[^0-9]//g')\"\n\tBUILD_YEAR_MONTH=\".$(date +\"%y%m\")\"\n\tif [ \".$ORIGIN\" == \"$LOCAL\" ]\n\tthen\n\t\tOFFSET=\"\"\n\t\tLOCAL=\"\"\n\t\tif [ \".0\" == \"$UNCOMMITTED\" ]\n\t\tthen\n\t\t\tUNCOMMITTED=\"\"\n\t\t\tBUILD_YEAR_MONTH=\"\"\n\t\tfi\n\tfi\n\tNEWVERSIONSTRING=\"1.$ORIGIN$OFFSET$LOCAL$UNCOMMITTED$BUILD_YEAR_MONTH\"\n\t/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $NEWVERSIONSTRING\" \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
77192A2223D6EA7A00EDB9BC /* Sources */ = { 77192A2223D6EA7A00EDB9BC /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
@ -1302,7 +1321,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "Flycut-iOS-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Flycut-iOS-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
}; };
name = Debug; name = Debug;
@ -1359,7 +1378,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Flycut-iOS-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Flycut-iOS-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
@ -1415,7 +1434,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Flycut-iOS.app/Flycut-iOS"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Flycut-iOS.app/Flycut-iOS";
}; };
name = Debug; name = Debug;
@ -1463,7 +1482,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Flycut-iOS.app/Flycut-iOS"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Flycut-iOS.app/Flycut-iOS";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
@ -1518,7 +1537,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TEST_TARGET_NAME = "Flycut-iOS"; TEST_TARGET_NAME = "Flycut-iOS";
}; };
name = Debug; name = Debug;
@ -1565,7 +1584,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0; SWIFT_VERSION = 5.0;
TEST_TARGET_NAME = "Flycut-iOS"; TEST_TARGET_NAME = "Flycut-iOS";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
@ -1614,11 +1633,14 @@
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Flycut_Prefix.pch; GCC_PREFIX_HEADER = Flycut_Prefix.pch;
GCC_PREPROCESSOR_DEFINITIONS = DEBUG; GCC_PREPROCESSOR_DEFINITIONS = (
DEBUG,
FLYCUT_MAC,
);
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications; INSTALL_PATH = /Applications;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10; MACOSX_DEPLOYMENT_TARGET = 10.7;
MARKETING_VERSION = 1.9.6; MARKETING_VERSION = 1.9.6;
PRODUCT_BUNDLE_IDENTIFIER = com.generalarcade.flycut; PRODUCT_BUNDLE_IDENTIFIER = com.generalarcade.flycut;
PRODUCT_NAME = Flycut; PRODUCT_NAME = Flycut;
@ -1647,12 +1669,12 @@
GCC_MODEL_TUNING = G5; GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Flycut_Prefix.pch; GCC_PREFIX_HEADER = Flycut_Prefix.pch;
GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_PREPROCESSOR_DEFINITIONS = FLYCUT_MAC;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ""; "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "";
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications; INSTALL_PATH = /Applications;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10; MACOSX_DEPLOYMENT_TARGET = 10.7;
MARKETING_VERSION = 1.9.6; MARKETING_VERSION = 1.9.6;
PRODUCT_BUNDLE_IDENTIFIER = com.generalarcade.flycut; PRODUCT_BUNDLE_IDENTIFIER = com.generalarcade.flycut;
PRODUCT_NAME = Flycut; PRODUCT_NAME = Flycut;

View file

@ -14,5 +14,7 @@
</array> </array>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict> </dict>
</plist> </plist>

View file

@ -16,7 +16,14 @@
#import "FlycutOperator.h" #import "FlycutOperator.h"
#import "MJCloudKitUserDefaultsSync/MJCloudKitUserDefaultsSync/MJCloudKitUserDefaultsSync.h" #import "MJCloudKitUserDefaultsSync/MJCloudKitUserDefaultsSync/MJCloudKitUserDefaultsSync.h"
@implementation FlycutOperator #ifdef FLYCUT_MAC
#import "AppController.h"
#endif
@implementation FlycutOperator {
NSDateFormatter *dateFormatterForFilename;
NSDateFormatter *dateFormatterForDirectory;
}
- (id)init - (id)init
{ {
@ -234,6 +241,7 @@
- (bool)saveFromStore:(FlycutStore*)store atIndex:(int)index withPrefix:(NSString*) prefix - (bool)saveFromStore:(FlycutStore*)store atIndex:(int)index withPrefix:(NSString*) prefix
{ {
#ifdef SANDBOXING #ifdef SANDBOXING
// This works fine when sandboxed. It just saves to ~/Library/Containers/.....
return NO; return NO;
# else # else
if ( [store jcListCount] > index ) { if ( [store jcListCount] > index ) {
@ -241,23 +249,92 @@
NSString *pbFullText = [self clippingStringWithCount:index inStore:store]; NSString *pbFullText = [self clippingStringWithCount:index inStore:store];
pbFullText = [pbFullText stringByReplacingOccurrencesOfString:@"\r" withString:@"\r\n"]; pbFullText = [pbFullText stringByReplacingOccurrencesOfString:@"\r" withString:@"\r\n"];
// Get the Desktop directory: if (!dateFormatterForFilename) {
NSArray *paths = NSSearchPathForDirectoriesInDomains // Date formatters are time-expensive to create, so create once and reuse.
(NSDesktopDirectory, NSUserDomainMask, YES); dateFormatterForFilename = [[NSDateFormatter alloc] init];
NSString *desktopDirectory = [paths objectAtIndex:0]; [dateFormatterForFilename setDateFormat:@"yyyy-MM-dd 'at' HH.mm.ss"];
}
// Get the timestamp string: // Get the timestamp string:
NSDate *currentDate = [NSDate date]; NSDate *currentDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; NSString *dateString = [dateFormatterForFilename stringFromDate:currentDate];
[dateFormatter setDateFormat:@"YYYY-MM-dd 'at' HH.mm.ss"];
NSString *dateString = [dateFormatter stringFromDate:currentDate];
// Make a file name to write the data to using the Desktop directory: // Make a file name
NSString *fileName = [NSString stringWithFormat:@"%@/%@%@Clipping %@.txt", NSString *fileName = [NSString stringWithFormat:@"%@%@Clipping %@.txt",
desktopDirectory, prefix, store == favoritesStore ? @"Favorite " : @"", dateString]; prefix, store == favoritesStore ? @"Favorite " : @"", dateString];
// Make a subdirectory, if doing autosave, to avoid a directory with too many files in it as that can make Finder effectively hang on launch if that directory were the desktop.
NSString *subdirectoryString = nil;
if ([prefix isEqualToString:@"Autosave "]) {
if (!dateFormatterForDirectory) {
// Date formatters are time-expensive to create, so create once and reuse.
dateFormatterForDirectory = [[NSDateFormatter alloc] init];
[dateFormatterForDirectory setDateFormat:@"'Autosave Clippings' yyyy/MM"];
}
subdirectoryString = [dateFormatterForDirectory stringFromDate:currentDate];
}
NSString *baseDirectoryString = nil;
NSString *fileNameWithPath = nil;
#ifdef FLYCUT_MAC
if ([AppController isAppSandboxed] && ![prefix isEqualToString:@"Autosave "]) {
// Since the app is sandboxed and this is not an auto-save, the user might want to say where to save it rather than just put it in ~/Library/Containers/..., so show a save dialog.
// Set the default name for the file and show the panel.
NSSavePanel* panel = [NSSavePanel savePanel];
[panel setNameFieldStringValue:fileName];
[panel setLevel:NSModalPanelWindowLevel];
[panel setAllowedFileTypes:@[@"txt"]];
if ([panel runModal] == NSFileHandlingPanelOKButton)
{
fileNameWithPath = [panel URL].path;
}
} else {
if ([prefix isEqualToString:@"Autosave "]) {
NSURL* autoSaveToLocation = [[NSUserDefaults standardUserDefaults] URLForKey:@"autoSaveToLocation"];
if (autoSaveToLocation) {
baseDirectoryString = autoSaveToLocation.path;
}
} else {
NSURL* saveToLocation = [[NSUserDefaults standardUserDefaults] URLForKey:@"saveToLocation"];
if (saveToLocation) {
baseDirectoryString = saveToLocation.path;
}
}
}
#endif
if (!fileNameWithPath) {
// An exact place to save wasn't set (like from a Save panel), so build one.
if (!baseDirectoryString) {
// Get the Desktop directory since nothing else was specified.
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDesktopDirectory, NSUserDomainMask, YES);
NSString *desktopDirectory = [paths objectAtIndex:0];
baseDirectoryString = desktopDirectory;
}
if (subdirectoryString) {
// Apply a subdirectory / subdirectories.
NSString *directoryPath = [NSString stringWithFormat:@"%@/%@",
baseDirectoryString, subdirectoryString];
[[NSFileManager defaultManager] createDirectoryAtPath:directoryPath
withIntermediateDirectories:YES
attributes:nil
error:nil];
baseDirectoryString = directoryPath;
}
// Make a file name to write the data to using the base directory:
fileNameWithPath = [NSString stringWithFormat:@"%@/%@",
baseDirectoryString, fileName];
}
// Save content to the file // Save content to the file
[pbFullText writeToFile:fileName [pbFullText writeToFile:fileNameWithPath
atomically:NO atomically:NO
encoding:NSNonLossyASCIIStringEncoding encoding:NSNonLossyASCIIStringEncoding
error:nil]; error:nil];
@ -303,7 +380,7 @@
return [self clippingStringWithCount:indexInt]; return [self clippingStringWithCount:indexInt];
} }
-(BOOL)shouldSkip:(NSString *)contents ofType:(NSString *)type -(BOOL)shouldSkip:(NSString *)contents ofType:(NSString *)type fromAvailableTypes:(NSArray<NSString *> *)availableTypes
{ {
// Check to see if we are skipping passwords based on length and characters. // Check to see if we are skipping passwords based on length and characters.
if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"skipPasswordFields"] ) if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"skipPasswordFields"] )
@ -316,10 +393,10 @@
__block bool skipClipping = NO; __block bool skipClipping = NO;
// Check the array of types to skip. // Check the array of types to skip.
if ( [[NSUserDefaults standardUserDefaults] boolForKey:@"skipPboardTypes"] ) if ( availableTypes && [[NSUserDefaults standardUserDefaults] boolForKey:@"skipPboardTypes"] )
{ {
NSSet *typesToSkip = [NSSet setWithArray: [[[[NSUserDefaults standardUserDefaults] stringForKey:@"skipPboardTypesList"] stringByReplacingOccurrencesOfString:@" " withString:@""] componentsSeparatedByString: @","]]; NSSet *typesToSkip = [NSSet setWithArray: [[[[NSUserDefaults standardUserDefaults] stringForKey:@"skipPboardTypesList"] stringByReplacingOccurrencesOfString:@" " withString:@""] componentsSeparatedByString: @","]];
NSSet *pasteBoardTypes = [NSSet setWithArray: [[NSPasteboard generalPasteboard] types]]; NSSet *pasteBoardTypes = [NSSet setWithArray: availableTypes];
if ( [pasteBoardTypes intersectsSet: typesToSkip] ) if ( [pasteBoardTypes intersectsSet: typesToSkip] )
{ {

View file

@ -8,6 +8,7 @@
#define kiCloudId @"iCloud.com.generalarcade.flycut" #define kiCloudId @"iCloud.com.generalarcade.flycut"
#define kFlycutHelperId @"com.generalarcade.flycuthelper" #define kFlycutHelperId @"com.generalarcade.flycuthelper"
// The SANDBOXING flag isn't tightly coupled with the sandboxing entitlement, so this amounts to more of a code policy flag than a feature availability flag at the moment. [AppController isAppSandboxed] is more effective for feature availability checks.
//#define SANDBOXING //#define SANDBOXING
#ifdef DEBUG #ifdef DEBUG

View file

@ -10,6 +10,7 @@
// //
#import "BezelWindow.h" #import "BezelWindow.h"
#import <AppKit/AppKit.h>
static const float lineHeight = 16; static const float lineHeight = 16;
@ -47,68 +48,70 @@ static const float lineHeight = 16;
sourceFieldBackground = [[RoundRecTextField alloc] initWithFrame:[self sourceFrame]]; sourceFieldBackground = [[RoundRecTextField alloc] initWithFrame:[self sourceFrame]];
[[self contentView] addSubview:sourceFieldBackground]; [[self contentView] addSubview:sourceFieldBackground];
[sourceFieldBackground setEditable:NO]; [sourceFieldBackground.textField setEditable:NO];
[sourceFieldBackground setTextColor:[NSColor whiteColor]]; [sourceFieldBackground.textField setTextColor:[NSColor whiteColor]];
[sourceFieldBackground setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:.45]]; [sourceFieldBackground.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.45)];
[sourceFieldBackground setDrawsBackground:YES]; [sourceFieldBackground.textField setBordered:NO];
[sourceFieldBackground setBordered:NO];
sourceFieldApp = [[RoundRecTextField alloc] initWithFrame:[self sourceFrameLeft]]; sourceFieldApp = [[RoundRecTextField alloc] initWithFrame:[self sourceFrameLeft]];
[[self contentView] addSubview:sourceFieldApp]; [[self contentView] addSubview:sourceFieldApp];
[sourceFieldApp setEditable:NO]; [sourceFieldApp.textField setEditable:NO];
[sourceFieldApp setTextColor:[NSColor whiteColor]]; [sourceFieldApp.textField setTextColor:[NSColor whiteColor]];
[sourceFieldApp setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:0]]; [sourceFieldApp.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.0)];
[sourceFieldApp setDrawsBackground:YES]; [sourceFieldApp.textField setBordered:NO];
[sourceFieldApp setBordered:NO]; [sourceFieldApp.textField setAlignment:NSLeftTextAlignment];
[sourceFieldApp setAlignment:NSLeftTextAlignment];
NSMutableParagraphStyle *textParagraph = [[NSMutableParagraphStyle alloc] init]; NSMutableParagraphStyle *textParagraph = [[NSMutableParagraphStyle alloc] init];
[textParagraph setLineSpacing:100.0]; [textParagraph setLineSpacing:100.0];
NSDictionary *attrDic = [NSDictionary dictionaryWithObjectsAndKeys:textParagraph, NSParagraphStyleAttributeName, nil]; NSDictionary *attrDic = [NSDictionary dictionaryWithObjectsAndKeys:textParagraph, NSParagraphStyleAttributeName, nil];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"" attributes:attrDic]; NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"" attributes:attrDic];
[sourceFieldApp setAllowsEditingTextAttributes:YES]; [sourceFieldApp.textField setAllowsEditingTextAttributes:YES];
[sourceFieldApp setAttributedStringValue:attrString]; [sourceFieldApp.textField setAttributedStringValue:attrString];
NSFont *font = [sourceFieldApp font]; NSFont *font = [sourceFieldApp.textField font];
NSFont *newFont = [NSFont fontWithName:[font fontName] size:font.pointSize*3/2]; NSFont *newFont = [NSFont fontWithName:[font fontName] size:font.pointSize*3/2];
[sourceFieldApp setFont:newFont]; [sourceFieldApp.textField setFont:newFont];
sourceFieldDate = [[RoundRecTextField alloc] initWithFrame:[self sourceFrameRight]]; sourceFieldDate = [[RoundRecTextField alloc] initWithFrame:[self sourceFrameRight]];
[[self contentView] addSubview:sourceFieldDate]; [[self contentView] addSubview:sourceFieldDate];
[sourceFieldDate setEditable:NO]; [sourceFieldDate.textField setEditable:NO];
[sourceFieldDate setTextColor:[NSColor whiteColor]]; [sourceFieldDate.textField setTextColor:[NSColor whiteColor]];
[sourceFieldDate setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:0]]; [sourceFieldDate.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.0)];
[sourceFieldDate setDrawsBackground:YES]; [sourceFieldDate.textField setBordered:NO];
[sourceFieldDate setBordered:NO]; [sourceFieldDate.textField setAlignment:NSRightTextAlignment];
[sourceFieldDate setAlignment:NSRightTextAlignment]; font = [sourceFieldDate.textField font];
font = [sourceFieldDate font];
newFont = [NSFont fontWithName:[font fontName] size:font.pointSize*5/4]; newFont = [NSFont fontWithName:[font fontName] size:font.pointSize*5/4];
[sourceFieldDate setFont:newFont]; [sourceFieldDate.textField setFont:newFont];
} }
NSRect textFrame = [self textFrame]; NSRect textFrame = [self textFrame];
textField = [[RoundRecTextField alloc] initWithFrame:textFrame]; textField = [[RoundRecTextField alloc] initWithFrame:textFrame];
[[self contentView] addSubview:textField]; [[self contentView] addSubview:textField];
[textField setEditable:NO]; [textField.textField setEditable:NO];
//[[textField cell] setScrollable:YES]; //[[textField cell] setScrollable:YES];
//[[textField cell] setWraps:NO]; //[[textField cell] setWraps:NO];
[textField setTextColor:[NSColor whiteColor]]; [textField.textField setTextColor:[NSColor whiteColor]];
[textField setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:.45]]; [textField.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.45)];
[textField setDrawsBackground:YES]; [textField.textField setBordered:NO];
[textField setBordered:NO]; [textField.textField setAlignment:NSLeftTextAlignment];
[textField setAlignment:NSLeftTextAlignment];
NSRect charFrame = [self charFrame]; NSRect charFrame = [self charFrame];
charField = [[RoundRecTextField alloc] initWithFrame:charFrame]; charField = [[RoundRecTextField alloc] initWithFrame:charFrame];
[[self contentView] addSubview:charField]; [[self contentView] addSubview:charField];
[charField setEditable:NO]; [charField.textField setEditable:NO];
[charField setTextColor:[NSColor whiteColor]]; [charField.textField setTextColor:[NSColor whiteColor]];
[charField setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:.45]]; [charField.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.45)];
[charField setDrawsBackground:YES]; [charField.textField setBordered:NO];
[charField setBordered:NO]; [charField.textField setAlignment:NSCenterTextAlignment];
[charField setAlignment:NSCenterTextAlignment]; [charField.textField setStringValue:@"Empty"];
[charField setStringValue:@"Empty"]; // Use Auto Layout for dynamic width.
charField.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[charField.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-charFrame.origin.y],
[charField.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor],
[charField.heightAnchor constraintEqualToConstant:charFrame.size.height],
]];
[self setInitialFirstResponder:textField]; [self setInitialFirstResponder:textField];
return self; return self;
@ -130,9 +133,9 @@ static const float lineHeight = 16;
NSRect charFrame = [self charFrame]; NSRect charFrame = [self charFrame];
[charField setFrame:charFrame]; [charField setFrame:charFrame];
if (showSourceField) if (showSourceField)
[sourceFieldBackground setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:.45]]; [sourceFieldBackground.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.45)];
else if ( nil != sourceFieldApp ) else if ( nil != sourceFieldApp )
[sourceFieldBackground setBackgroundColor:[NSColor colorWithCalibratedWhite:0.1 alpha:0]]; [sourceFieldBackground.background.layer setBackgroundColor:CGColorCreateGenericRGB(0.1, 0.1, 0.1, 0.0)];
showSourceField = savedShowSourceField; showSourceField = savedShowSourceField;
@ -161,7 +164,6 @@ static const float lineHeight = 16;
{ {
NSRect frame = [self sourceFrame]; NSRect frame = [self sourceFrame];
frame.size.width = frame.size.width * 1 / 3 - 5; frame.size.width = frame.size.width * 1 / 3 - 5;
frame.origin.x += 5;
return frame; return frame;
} }
@ -219,7 +221,7 @@ static const float lineHeight = 16;
[newChar retain]; [newChar retain];
[charString release]; [charString release];
charString = newChar; charString = newChar;
[charField setStringValue:charString]; [charField.textField setStringValue:charString];
} }
- (void)setText:(NSString *)newText - (void)setText:(NSString *)newText
@ -231,7 +233,7 @@ static const float lineHeight = 16;
[newText retain]; [newText retain];
[bezelText release]; [bezelText release];
bezelText = newText; bezelText = newText;
[textField setStringValue:bezelText]; [textField.textField setStringValue:bezelText];
} }
- (void)setSourceIcon:(NSImage *)newSourceIcon - (void)setSourceIcon:(NSImage *)newSourceIcon
@ -250,7 +252,7 @@ static const float lineHeight = 16;
return; return;
// Ensure that the source will fit in the screen space available, and truncate nicely if need be. // Ensure that the source will fit in the screen space available, and truncate nicely if need be.
NSDictionary *attributes = @{NSFontAttributeName: sourceFieldApp.font}; NSDictionary *attributes = @{NSFontAttributeName: sourceFieldApp.textField.font};
CGSize size = [newSource sizeWithAttributes:attributes]; // How big is this string when drawn in this font? CGSize size = [newSource sizeWithAttributes:attributes]; // How big is this string when drawn in this font?
if (size.width >= sourceFieldApp.frame.size.width - 5) if (size.width >= sourceFieldApp.frame.size.width - 5)
{ {
@ -265,7 +267,7 @@ static const float lineHeight = 16;
[newSource retain]; [newSource retain];
[sourceText release]; [sourceText release];
sourceText = newSource; sourceText = newSource;
[sourceFieldApp setStringValue:sourceText]; [sourceFieldApp.textField setStringValue:sourceText];
} }
- (void)setDate:(NSString *)newDate - (void)setDate:(NSString *)newDate
@ -275,7 +277,7 @@ static const float lineHeight = 16;
[newDate retain]; [newDate retain];
[dateText release]; [dateText release];
dateText = newDate; dateText = newDate;
[sourceFieldDate setStringValue:dateText]; [sourceFieldDate.textField setStringValue:dateText];
} }
- (void)setColor:(BOOL)value - (void)setColor:(BOOL)value

View file

@ -12,9 +12,9 @@
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
@interface RoundRecTextField : NSTextField { @interface RoundRecTextField : NSView
IBOutlet RoundRecTextField *characterBackground;
IBOutlet RoundRecTextField *textBackground; @property (nonatomic, nonnull, readonly) NSTextField *textField;
} @property (nonatomic, nonnull, readonly) NSView *background;
@end @end

View file

@ -13,41 +13,41 @@
#import "RoundRecTextField.h" #import "RoundRecTextField.h"
#import "RoundRecBezierPath.h" #import "RoundRecBezierPath.h"
// Okay, on doing some reading, the -best- way to handle this is probably to cache
// an NSImage on the init and then (as needed) composite it to the back of the view.
// We can then turn the rectangles on and off by compositing or not compositing the
// images.
// This can wait for another time.
@implementation RoundRecTextField @implementation RoundRecTextField
// We may want to make this a more flexible class sometime by taking radius as an argument. // We may want to make this a more flexible class sometime by taking radius as an argument.
// Until then, this is kind of useless code.
/*
- (id)initWithFrame:(NSRect)frame { - (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self) { if (self) {
// Initialization code here. _background = [[NSView alloc] initWithFrame:frame];
[self addSubview:_background];
[_background setWantsLayer:YES];
[_background.layer setCornerRadius:8];
_background.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_background.topAnchor constraintEqualToAnchor:self.topAnchor],
[_background.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_background.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[_background.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
]];
_textField = [[NSTextField alloc] initWithFrame:frame];
[self addSubview:_textField];
[_textField setDrawsBackground:NO];
// Set 8px leading and trailing padding.
_textField.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_textField.topAnchor constraintEqualToAnchor:self.topAnchor],
[_textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_textField.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:8],
[_textField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-8],
]];
} }
return self; return self;
} }
*/
- (BOOL)isOpaque { @end
return NO;
}
- (void)drawRect:(NSRect)rect {
// Oh, the hackishness.
NSBezierPath *roundedRec = [NSBezierPath bezierPathWithRoundRectInRect:rect radius:8];
[[self backgroundColor] set];
[roundedRec fill];
[self setDrawsBackground:NO];
// We might eventually want to pass [super drawRect] something smaller than rect, to ensure that we don't bleed over the corners
[super drawRect:rect];
[self setDrawsBackground:YES];
}
@end

44
configureAppSandboxing.sh Executable file
View file

@ -0,0 +1,44 @@
#!/bin/bash
appSandboxing=false
defineSandboxing=false
if [ "$1" == "YES" ]
then
appSandboxing=true
defineSandboxing=false
elif [ "$1" == "NO" ]
then
appSandboxing=false
defineSandboxing=false
elif [ "$1" == "SANDBOXING" ]
then
appSandboxing=true
defineSandboxing=true
else
echo "Run with parameter YES or NO to enable or disable app sandboxing."
echo "Or with parameter SANDBOXING to enable or app sandboxing and define SANDBOXING"
echo " in the prefix header."
exit -1
fi
if [ "$defineSandboxing" == "true" ]
then
sed -i '' 's|^//\(#define SANDBOXING\) *$|\1|' Flycut_Prefix.pch
git add Flycut_Prefix.pch
else
sed -i '' 's|^\(#define SANDBOXING\) *$|//\1|' Flycut_Prefix.pch
git add Flycut_Prefix.pch
fi
for key in com.apple.security.app-sandbox com.apple.security.files.user-selected.read-write
do
for entitlements in $(git grep -l -e ">$key<")
do
/usr/libexec/PlistBuddy -c "Set :$key $appSandboxing" "$entitlements"
git add "$entitlements"
done
done
git commit -m "App Sandbox $(if [ "$appSandboxing" == "true" ] ; then echo "ON" ; else echo "OFF" ; fi)$(if [ "$defineSandboxing" == "true" ] ; then echo " with define" ; fi)"