Skip to content

Commit

Permalink
Added multiple screen support and improved transition between connect…
Browse files Browse the repository at this point in the history
…ing/disconnecting screens.
  • Loading branch information
mattDavo committed May 24, 2020
1 parent e374577 commit ec79d87
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 33 deletions.
10 changes: 5 additions & 5 deletions Yippy.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.3.0;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = MatthewDavidson.Yippy;
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -1367,7 +1367,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.3.0;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = MatthewDavidson.Yippy;
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -1541,7 +1541,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.3.0;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = MatthewDavidson.YippyBeta;
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME) Beta";
Expand Down Expand Up @@ -1666,7 +1666,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.3.0;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = MatthewDavidson.YippyBeta;
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME) Beta";
Expand Down Expand Up @@ -1798,7 +1798,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.3.0;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = MatthewDavidson.YippyXCTest;
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
1 change: 1 addition & 0 deletions Yippy/Sources/Extensions/NSMenuItem+Functional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Cocoa

extension NSMenuItem {

@discardableResult
func with(submenu: NSMenu) -> NSMenuItem {
self.submenu = submenu
return self
Expand Down
8 changes: 4 additions & 4 deletions Yippy/Sources/Models/Controller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Controller {
self.statusItem.menu = Self.createMenu(settings: settings, state: state, target: self)

// Create yippy window controller
self.yippyWindowController = Self.createYippyWindowController(isHistoryPanelShown: state.isHistoryPanelShown, panelPosition: state.panelPosition, disposeBag: state.disposeBag)
self.yippyWindowController = Self.createYippyWindowController(state: state, disposeBag: state.disposeBag)

// Create preview window controllers
self.previewWindowController = Self.createPreviewWindowController(previewItem: state.previewHistoryItem, disposeBag: state.disposeBag)
Expand Down Expand Up @@ -152,13 +152,13 @@ class Controller {
}
}

static func createYippyWindowController(isHistoryPanelShown: BehaviorRelay<Bool>, panelPosition: BehaviorRelay<PanelPosition>, disposeBag: DisposeBag) -> YippyWindowController {
static func createYippyWindowController(state: State, disposeBag: DisposeBag) -> YippyWindowController {
let controller = YippyWindowController.createYippyWindowController()
controller
.subscribeTo(toggle: isHistoryPanelShown)
.subscribeTo(toggle: state.isHistoryPanelShown)
.disposed(by: disposeBag)
controller
.subscribePositionTo(position: panelPosition)
.subscribeFrameTo(position: state.panelPosition.asObservable(), screen: state.currentScreen.asObservable())
.disposed(by: disposeBag)
return controller
}
Expand Down
10 changes: 10 additions & 0 deletions Yippy/Sources/Models/History/HistoryItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ class HistoryItem: NSObject {
pasteboard.setData(data, forType: .color)
return NSColor(from: pasteboard)
}

private func isStringLink(string: String) -> Bool {
let types: NSTextCheckingResult.CheckingType = [.link]
let detector = try? NSDataDetector(types: types.rawValue)
guard (detector != nil && string.count > 0) else { return false }
if detector!.numberOfMatches(in: string, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, string.count)) > 0 {
return true
}
return false
}
}

// MARK: - HistoryItem+NSPasteboardWriting
Expand Down
27 changes: 13 additions & 14 deletions Yippy/Sources/Models/PanelPosition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,32 @@ enum PanelPosition: Int, Codable, CaseIterable {
case centerLarge = 6
case fullScreen = 7

var frame: NSRect {
// TODO: Use NSEvent.mouseLocation to choose which screen
public func getFrame(forScreen screen: NSScreen) -> NSRect {
switch self {
case .right:
return NSRect(x: NSScreen.main!.frame.maxX - Constants.panel.menuWidth, y: 0, width: Constants.panel.menuWidth, height: NSScreen.main!.frame.maxY)
return NSRect(x: screen.frame.maxX - Constants.panel.menuWidth, y: screen.frame.minY, width: Constants.panel.menuWidth, height: screen.frame.maxY)
case .left:
return NSRect(x: 0, y: 0, width: Constants.panel.menuWidth, height: NSScreen.main!.frame.maxY)
return NSRect(x: screen.frame.minX, y: screen.frame.minY, width: Constants.panel.menuWidth, height: screen.frame.maxY)
case .top:
return NSRect(x: 0, y: NSScreen.main!.frame.maxY - Constants.panel.menuHeight, width: NSScreen.main!.frame.width, height: Constants.panel.menuHeight)
return NSRect(x: screen.frame.minX, y: screen.frame.maxY - Constants.panel.menuHeight, width: screen.frame.width, height: Constants.panel.menuHeight)
case .bottom:
return NSRect(x: 0, y: 0, width: NSScreen.main!.frame.width, height: Constants.panel.menuHeight)
return NSRect(x: screen.frame.minX, y: screen.frame.minY, width: screen.frame.width, height: Constants.panel.menuHeight)
case .centerSmall:
let size = NSSize(width: NSScreen.main!.frame.width / 2, height: NSScreen.main!.frame.height / 2)
return Self.centerRect(ofSize: size, inRect: NSScreen.main!.frame)
let size = NSSize(width: screen.frame.width / 2, height: screen.frame.height / 2)
return Self.centerRect(ofSize: size, inRect: screen.frame)
case .centerMedium:
let size = NSSize(width: NSScreen.main!.frame.width * 0.7, height: NSScreen.main!.frame.height * 0.7)
return Self.centerRect(ofSize: size, inRect: NSScreen.main!.frame)
let size = NSSize(width: screen.frame.width * 0.7, height: screen.frame.height * 0.7)
return Self.centerRect(ofSize: size, inRect: screen.frame)
case .centerLarge:
let size = NSSize(width: NSScreen.main!.frame.width * 0.85, height: NSScreen.main!.frame.height * 0.85)
return Self.centerRect(ofSize: size, inRect: NSScreen.main!.frame)
let size = NSSize(width: screen.frame.width * 0.85, height: screen.frame.height * 0.85)
return Self.centerRect(ofSize: size, inRect: screen.frame)
case .fullScreen:
return NSScreen.main!.frame
return screen.frame
}
}

private static func centerRect(ofSize size: NSSize, inRect rect: NSRect) -> NSRect {
return NSRect(origin: NSPoint(x: (rect.width - size.width) / 2, y: (rect.height - size.height) / 2), size: size)
return NSRect(origin: NSPoint(x: (rect.width - size.width) / 2 + rect.minX, y: (rect.height - size.height) / 2 + rect.minY), size: size)
}

var title: String {
Expand Down
23 changes: 22 additions & 1 deletion Yippy/Sources/Models/State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class State {

var panelPosition: BehaviorRelay<PanelPosition>

var currentScreen: BehaviorRelay<NSScreen>

var previewHistoryItem: BehaviorRelay<HistoryItem?>

var launchAtLogin: BehaviorRelay<Bool>
Expand Down Expand Up @@ -51,6 +53,7 @@ class State {
self.launchAtLogin = BehaviorRelay<Bool>(value: LoginServiceKit.isExistLoginItems())
self.showsRichText = BehaviorRelay<Bool>(value: settings.showsRichText)
self.pastesRichText = BehaviorRelay<Bool>(value: settings.pastesRichText)
self.currentScreen = BehaviorRelay<NSScreen>(value: Self.getCurrentScreen(forMouseLocation: NSEvent.mouseLocation))
self.disposeBag = disposeBag

// Setup history
Expand All @@ -65,8 +68,8 @@ class State {
// Setup pasteboard monitor
self.pasteboardMonitor = PasteboardMonitor(pasteboard: NSPasteboard.general, changeCount: settings.pasteboardChangeCount, delegate: self.history)

//
Self.monitorPastesRichText(state: self)
Self.monitorMousePosition(state: self)
}

// MARK: - Constructor Helpers
Expand All @@ -84,4 +87,22 @@ class State {
HistoryItem.pastesRichText = $0
}).disposed(by: state.disposeBag)
}

static func monitorMousePosition(state: State) {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
let currentScreen = getCurrentScreen(forMouseLocation: NSEvent.mouseLocation)
if currentScreen != state.currentScreen.value {
state.currentScreen.accept(currentScreen)
}
}
}

static func getCurrentScreen(forMouseLocation location: NSPoint) -> NSScreen {
for screen in NSScreen.screens {
if screen.frame.contains(location) {
return screen
}
}
return NSScreen.main!
}
}
11 changes: 5 additions & 6 deletions Yippy/Sources/Windows/Yippy/YippyWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ class YippyWindowController: NSWindowController {
})
}

func subscribePositionTo(position: BehaviorRelay<PanelPosition>) -> Disposable {
return position
.subscribe(onNext: {
[] in
self.window?.setFrame($0.frame, display: true)
})
func subscribeFrameTo(position: Observable<PanelPosition>, screen: Observable<NSScreen>) -> Disposable {
Observable.combineLatest(position, screen).subscribe(onNext: {
(position, screen) in
self.window?.setFrame(position.getFrame(forScreen: screen), display: true)
})
}
}
6 changes: 3 additions & 3 deletions YippyUITests/YippyUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ class YippyUITests: XCTestCase {
XCTAssertTrue(app.yippyWindow.exists)

// Check window location is .right
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.right.frame.midX)
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.right.getFrame(forScreen: NSScreen.main!).midX)

// Change to position left
app.statusItemButton.click()
app.positionButton.click()
app.positionLeftButton.click()

// Check window location is .left
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.left.frame.midX)
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.left.getFrame(forScreen: NSScreen.main!).midX)

// Change to position bottom
app.statusItemButton.click()
Expand All @@ -139,7 +139,7 @@ class YippyUITests: XCTestCase {
app.positionRightButton.click()

// Check window location is .right
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.right.frame.midX)
XCTAssertEqual(app.yippyWindow.frame.midX, PanelPosition.right.getFrame(forScreen: NSScreen.main!).midX)
}

func testEmptyYippyHistory() {
Expand Down

0 comments on commit ec79d87

Please sign in to comment.