From 891aefa9035c5772f00aa1040d0afa8174f47749 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Tue, 22 Aug 2023 19:57:55 +0900 Subject: [PATCH 01/33] =?UTF-8?q?fix:=20toolbarView=EC=9D=98=20=EC=96=B4?= =?UTF-8?q?=EC=83=89=ED=95=9C=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 1 + Box42/Toolbar/ToolbarViewController.swift | 33 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 538078f..0a47934 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -12,6 +12,7 @@ class BoxBaseContainerViewController: NSViewController { var splitView: BoxBaseSplitView! = BoxBaseSplitView() var contentGroup: BoxContentsViewGroup! = BoxContentsViewGroup() var toolbarGroup: BoxToolbarViewGroup! = BoxToolbarViewGroup() + var toolbarGroupVC: ToolbarViewController! = ToolbarViewController() var functionGroupVC: BoxFunctionViewController! = BoxFunctionViewController() var buttonGroup: BoxButtonViewGroup! var leftContainer: MovableContainerView! diff --git a/Box42/Toolbar/ToolbarViewController.swift b/Box42/Toolbar/ToolbarViewController.swift index ea32aab..ebc4744 100644 --- a/Box42/Toolbar/ToolbarViewController.swift +++ b/Box42/Toolbar/ToolbarViewController.swift @@ -8,24 +8,23 @@ import Cocoa class ToolbarViewController: NSViewController { - var displayURL = DisplayURLInToolbar() - var goBackButton: GoBackInToolbar? - var goForwardButton: GoForwardInToolbar? - var reloadPageButton: ReloadPageViaToolbar? - var goHomePageViaButton: GoHomePageViaToolbar? - var sidebarLeading: SideBarLeading? - +// var displayURL = DisplayURLInToolbar() +// var goBackButton: GoBackInToolbar? +// var goForwardButton: GoForwardInToolbar? +// var reloadPageButton: ReloadPageViaToolbar? +// var goHomePageViaButton: GoHomePageViaToolbar? +// var sidebarLeading: SideBarLeading? +// override func loadView() { - displayURL = DisplayURLInToolbar() - sidebarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: sidebar) - goBackButton = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: goBack) - goForwardButton = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: goFoward) - reloadPageButton = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: reloadPage) - goHomePageViaButton = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: goToHome) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") +// displayURL = DisplayURLInToolbar() +// sidebarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: sidebar) +// goBackButton = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: goBack) +// goForwardButton = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: goFoward) +// reloadPageButton = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: reloadPage) +// goHomePageViaButton = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: goToHome) + + let toolbarViewGroup = BoxToolbarViewGroup() + self.view = toolbarViewGroup } override func viewDidLoad() { From 6ae3e21cdb6d172bb1593e3d6035fa486612606a Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 23 Aug 2023 03:04:14 +0900 Subject: [PATCH 02/33] =?UTF-8?q?refactor:=20toolbarVC=EC=99=80=20toolbarV?= =?UTF-8?q?iew=EC=9D=98=20clean=20architecure=EB=A5=BC=20=EC=A7=80?= =?UTF-8?q?=ED=96=A5=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 23 ++++-- Box42/Toolbar/ToolbarViewController.swift | 21 ++--- Box42/Toolbar/View/BoxToolbarViewGroup.swift | 81 +++++++++++++++---- 3 files changed, 89 insertions(+), 36 deletions(-) diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 0a47934..f170ec4 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -9,11 +9,11 @@ import Cocoa import SnapKit class BoxBaseContainerViewController: NSViewController { - var splitView: BoxBaseSplitView! = BoxBaseSplitView() - var contentGroup: BoxContentsViewGroup! = BoxContentsViewGroup() - var toolbarGroup: BoxToolbarViewGroup! = BoxToolbarViewGroup() - var toolbarGroupVC: ToolbarViewController! = ToolbarViewController() - var functionGroupVC: BoxFunctionViewController! = BoxFunctionViewController() + var splitView: BoxBaseSplitView = BoxBaseSplitView() + var contentGroup: BoxContentsViewGroup = BoxContentsViewGroup() + var toolbarGroupVC: ToolbarViewController = ToolbarViewController() + var functionGroupVC: BoxFunctionViewController = BoxFunctionViewController() + let windowViewGroup: WindowButtonViewController = WindowButtonViewController() var buttonGroup: BoxButtonViewGroup! var leftContainer: MovableContainerView! @@ -54,21 +54,28 @@ class BoxBaseContainerViewController: NSViewController { private func leftContainerInit() { leftContainer = MovableContainerView() leftContainer.addSubview(buttonGroup) - leftContainer.addSubview(toolbarGroup) + leftContainer.addSubview(windowViewGroup.view) + leftContainer.addSubview(toolbarGroupVC.view) leftContainer.addSubview(functionGroupVC.view) leftContainerAutolayout() leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width } private func leftContainerAutolayout() { - toolbarGroup.snp.makeConstraints { make in + windowViewGroup.view.snp.makeConstraints { make in make.top.equalTo(leftContainer).offset(Constants.UI.GroupAutolayout) make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) make.left.equalTo(leftContainer) } + toolbarGroupVC.view.snp.makeConstraints { make in + make.top.equalTo(windowViewGroup.view.snp.bottom).offset(Constants.UI.GroupAutolayout) + make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) + make.left.equalTo(leftContainer) + } + buttonGroup.snp.makeConstraints { make in - make.top.equalTo(toolbarGroup.snp.bottom).offset(Constants.UI.GroupAutolayout) + make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.GroupAutolayout) make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) make.left.equalTo(leftContainer) } diff --git a/Box42/Toolbar/ToolbarViewController.swift b/Box42/Toolbar/ToolbarViewController.swift index ebc4744..c5df281 100644 --- a/Box42/Toolbar/ToolbarViewController.swift +++ b/Box42/Toolbar/ToolbarViewController.swift @@ -8,22 +8,15 @@ import Cocoa class ToolbarViewController: NSViewController { -// var displayURL = DisplayURLInToolbar() -// var goBackButton: GoBackInToolbar? -// var goForwardButton: GoForwardInToolbar? -// var reloadPageButton: ReloadPageViaToolbar? -// var goHomePageViaButton: GoHomePageViaToolbar? -// var sidebarLeading: SideBarLeading? -// override func loadView() { -// displayURL = DisplayURLInToolbar() -// sidebarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: sidebar) -// goBackButton = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: goBack) -// goForwardButton = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: goFoward) -// reloadPageButton = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: reloadPage) -// goHomePageViaButton = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: goToHome) - let toolbarViewGroup = BoxToolbarViewGroup() + + toolbarViewGroup.sidebar = sidebar + toolbarViewGroup.goBack = goBack + toolbarViewGroup.goFoward = goFoward + toolbarViewGroup.reloadPage = reloadPage + toolbarViewGroup.goToHome = goToHome + self.view = toolbarViewGroup } diff --git a/Box42/Toolbar/View/BoxToolbarViewGroup.swift b/Box42/Toolbar/View/BoxToolbarViewGroup.swift index ac17e8c..3d63053 100644 --- a/Box42/Toolbar/View/BoxToolbarViewGroup.swift +++ b/Box42/Toolbar/View/BoxToolbarViewGroup.swift @@ -9,23 +9,76 @@ import AppKit import SnapKit class BoxToolbarViewGroup: NSView { - var toolbarVC: ToolbarViewController? + var displayURL = DisplayURLInToolbar() + lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.goBack?() }) + lazy var goBackButton: GoBackInToolbar = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.goFoward?()} ) + lazy var goForwardButton: GoForwardInToolbar = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.reloadPage?() }) + lazy var reloadPageButton: ReloadPageViaToolbar = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: { self.goToHome?() }) + lazy var goHomePageViaButton: GoHomePageViaToolbar = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: { self.sidebar?() }) - init() { -// toolbarVC = ToolbarViewController(nibName: nil, bundle: nil) - - super.init(frame: NSRect(x: 0, y: 0, width: BoxSizeManager.shared.size.width - BoxSizeManager.shared.toolbarGroupSize.width, height: BoxSizeManager.shared.toolbarGroupSize.height)) + var goBack: (() -> Void)? + var goFoward: (() -> Void)? + var reloadPage: (() -> Void)? + var goToHome: (() -> Void)? + var sidebar: (() -> Void)? + + override init(frame: NSRect) { + super.init(frame: frame) + setupViews() + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + setupConstraints() + } + + private func setupViews() { + self.addSubview(displayURL) + self.addSubview(sidebarLeading) + self.addSubview(goBackButton) + self.addSubview(goForwardButton) + self.addSubview(reloadPageButton) + self.addSubview(goHomePageViaButton) + } + + private func setupConstraints() { + displayURL.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.right.equalToSuperview() + } - self.wantsLayer = true -// self.addSubview(toolbarVC!.view) + sidebarLeading.snp.makeConstraints { make in + make.top.equalTo(displayURL).offset(10) + make.bottom.equalToSuperview() + make.left.equalToSuperview() + make.width.equalTo(goBackButton) + } + + goBackButton.snp.makeConstraints { make in + make.top.bottom.equalTo(sidebarLeading) + make.left.equalTo(sidebarLeading.snp.right).offset(10) + make.width.equalTo(goForwardButton) + } + + goForwardButton.snp.makeConstraints { make in + make.top.bottom.equalTo(sidebarLeading) + make.left.equalTo(goBackButton.snp.right).offset(10) + make.width.equalTo(reloadPageButton) + } + + reloadPageButton.snp.makeConstraints { make in + make.top.bottom.equalTo(sidebarLeading) + make.left.equalTo(goForwardButton.snp.right).offset(10) + make.width.equalTo(goHomePageViaButton) + } - toolbarVC?.view.translatesAutoresizingMaskIntoConstraints = false - toolbarVC?.view.snp.makeConstraints { make in - make.edges.equalTo(self) + goHomePageViaButton.snp.makeConstraints { make in + make.top.bottom.equalTo(sidebarLeading) + make.left.equalTo(reloadPageButton.snp.right).offset(10) + make.right.equalToSuperview() } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } } From 3538c0325013046b836ae2223a66595ac09e89f9 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 23 Aug 2023 03:05:01 +0900 Subject: [PATCH 03/33] =?UTF-8?q?feat:=20window=20toolbar=EB=A5=BC=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=EC=9C=BC=EB=A1=9C=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Window/BoxWindowController.swift | 6 +- Box42/Window/View/WindowCloseButton.swift | 31 ++++++++++ Box42/Window/View/WindowMaximizeButton.swift | 31 ++++++++++ Box42/Window/View/WindowMinimizeButton.swift | 31 ++++++++++ Box42/Window/View/WindowViewGroup.swift | 56 +++++++++++++++++++ Box42/Window/WindowButtonViewController.swift | 36 ++++++++++++ 6 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 Box42/Window/View/WindowCloseButton.swift create mode 100644 Box42/Window/View/WindowMaximizeButton.swift create mode 100644 Box42/Window/View/WindowMinimizeButton.swift create mode 100644 Box42/Window/View/WindowViewGroup.swift create mode 100644 Box42/Window/WindowButtonViewController.swift diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index dc69045..063dd96 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -8,11 +8,9 @@ import Cocoa class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelegate { - override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect - let styleMask: NSWindow.StyleMask = [.resizable, .closable, .miniaturizable, .fullSizeContentView, .titled] - + let styleMask: NSWindow.StyleMask = [.resizable, .closable, .miniaturizable, .fullSizeContentView] let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) windowInstance.titlebarAppearsTransparent = true @@ -30,7 +28,7 @@ class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelega windowInstance.delegate = self - setupToolbar() +// setupToolbar() } required init?(coder: NSCoder) { diff --git a/Box42/Window/View/WindowCloseButton.swift b/Box42/Window/View/WindowCloseButton.swift new file mode 100644 index 0000000..0e9a747 --- /dev/null +++ b/Box42/Window/View/WindowCloseButton.swift @@ -0,0 +1,31 @@ +// +// WindowCloseButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowCloseButton: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.title = "X" // 기본적인 X 모양으로 표시. 이미지나 다른 디자인을 원하시면 변경하실 수 있습니다. + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(closeAction) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func closeAction() { + callback?() + } +} diff --git a/Box42/Window/View/WindowMaximizeButton.swift b/Box42/Window/View/WindowMaximizeButton.swift new file mode 100644 index 0000000..dde3691 --- /dev/null +++ b/Box42/Window/View/WindowMaximizeButton.swift @@ -0,0 +1,31 @@ +// +// WindowMaximizeButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowMaximizeButton: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.title = "□" // 기본적인 □ 모양으로 표시. 변경 가능. + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(maximizeAction) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func maximizeAction() { + callback?() + } +} diff --git a/Box42/Window/View/WindowMinimizeButton.swift b/Box42/Window/View/WindowMinimizeButton.swift new file mode 100644 index 0000000..e940fb5 --- /dev/null +++ b/Box42/Window/View/WindowMinimizeButton.swift @@ -0,0 +1,31 @@ +// +// WindowMinimizeButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowMinimizeButton: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.title = "_" // 기본적인 _ 모양으로 표시. 변경 가능. + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(minimizeAction) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func minimizeAction() { + callback?() + } +} diff --git a/Box42/Window/View/WindowViewGroup.swift b/Box42/Window/View/WindowViewGroup.swift new file mode 100644 index 0000000..f96abec --- /dev/null +++ b/Box42/Window/View/WindowViewGroup.swift @@ -0,0 +1,56 @@ +// +// WindowViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit +import SnapKit + +class WindowViewGroup: NSView { + lazy var windowClose: WindowCloseButton = WindowCloseButton(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.close?() }) + lazy var windowMinimize: WindowMinimizeButton = WindowMinimizeButton(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.minimize?()} ) + lazy var windowMaximize: WindowMaximizeButton = WindowMaximizeButton(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.maximize?() }) + + var close: (() -> Void)? + var minimize: (() -> Void)? + var maximize: (() -> Void)? + + override init(frame: NSRect) { + super.init(frame: frame) + setupViews() + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + setupConstraints() + } + + private func setupViews() { + self.addSubview(windowClose) + self.addSubview(windowMinimize) + self.addSubview(windowMaximize) + } + + private func setupConstraints() { + + windowClose.snp.makeConstraints { make in + make.top.left.bottom.equalToSuperview() + make.width.equalTo(windowMinimize) + } + + windowMinimize.snp.makeConstraints { make in + make.top.bottom.equalTo(windowClose) + make.left.equalTo(windowClose.snp.right).offset(10) + make.width.equalTo(windowMaximize) + } + + windowMaximize.snp.makeConstraints { make in + make.top.right.bottom.equalToSuperview() + make.left.equalTo(windowMinimize.snp.right).offset(10) + } + } +} diff --git a/Box42/Window/WindowButtonViewController.swift b/Box42/Window/WindowButtonViewController.swift new file mode 100644 index 0000000..511ef8c --- /dev/null +++ b/Box42/Window/WindowButtonViewController.swift @@ -0,0 +1,36 @@ +// +// WindowButtonViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import Cocoa + +class WindowButtonViewController: NSViewController { + override func loadView() { + let windowViewGroup = WindowViewGroup() + + windowViewGroup.close = windowClose + windowViewGroup.minimize = windowMin + windowViewGroup.maximize = windowMax + + self.view = windowViewGroup + } + + override func viewDidLoad() { + super.viewDidLoad() + } + + func windowClose() { + print("close") + } + + func windowMin() { + print("min") + } + + func windowMax() { + print("max") + } +} From f913310b3db0176d6c5ab12bdb216cd7e3a7d6f2 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 23 Aug 2023 03:05:42 +0900 Subject: [PATCH 04/33] =?UTF-8?q?chore:=20=EA=B0=95=EC=A0=9C=EC=96=B8?= =?UTF-8?q?=EB=9E=A9=ED=95=91=EC=9D=84=20=ED=95=B4=EC=A0=9C=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/View/BoxButtonViewGroup.swift | 2 +- Box42/FunctionButton/View/BoxFunctionViewGroup.swift | 10 +++++----- Box42/Main/BoxViewController.swift | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Box42/Box/View/BoxButtonViewGroup.swift b/Box42/Box/View/BoxButtonViewGroup.swift index 44a2299..12939d5 100644 --- a/Box42/Box/View/BoxButtonViewGroup.swift +++ b/Box42/Box/View/BoxButtonViewGroup.swift @@ -9,7 +9,7 @@ import Cocoa import SnapKit class BoxButtonViewGroup: NSView { - var boxVM: WebViewModel! = WebViewModel() + var boxVM: WebViewModel = WebViewModel() var pinSwitch : NSSwitch = NSSwitch() var clickAction: ((NSButton) -> Void)? var lastAddedButton: NSView? diff --git a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift index 9e5fa88..2570826 100644 --- a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -9,11 +9,11 @@ import AppKit import SnapKit class BoxFunctionViewGroup: NSView { - lazy var preferenceButton: PreferenceButtonView! = PreferenceButtonView(image: NSImage(imageLiteralResourceName: "plus"), completion: { self.preferenceAction?() }) - lazy var pinButton: PinButtonView! = PinButtonView(image: NSImage(imageLiteralResourceName: "pin"), completion: { self.pinAction?() }) - lazy var quitButton: QuitButtonView! = QuitButtonView(image: NSImage(imageLiteralResourceName: "figure.snowboarding"), completion: { self.quitAction?() }) - lazy var boxButton: BoxFunctionButtonView! = BoxFunctionButtonView(image: NSImage(imageLiteralResourceName: "shippingbox"), completion: { self.boxAction?() }) - lazy var divider: NSBox! = TopDivider(completion: { self.dividerAction?() }) + lazy var preferenceButton: PreferenceButtonView = PreferenceButtonView(image: NSImage(imageLiteralResourceName: "plus"), completion: { self.preferenceAction?() }) + lazy var pinButton: PinButtonView = PinButtonView(image: NSImage(imageLiteralResourceName: "pin"), completion: { self.pinAction?() }) + lazy var quitButton: QuitButtonView = QuitButtonView(image: NSImage(imageLiteralResourceName: "figure.snowboarding"), completion: { self.quitAction?() }) + lazy var boxButton: BoxFunctionButtonView = BoxFunctionButtonView(image: NSImage(imageLiteralResourceName: "shippingbox"), completion: { self.boxAction?() }) + lazy var divider: NSBox = TopDivider(completion: { self.dividerAction?() }) var preferenceAction: (() -> Void)? var pinAction: (() -> Void)? diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index a9692c8..551ba31 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -9,12 +9,11 @@ import AppKit import WebKit class BoxViewController: NSViewController { - var boxView: BoxBaseContainerViewController! = BoxBaseContainerViewController() + var boxView: BoxBaseContainerViewController = BoxBaseContainerViewController() var gradientLayer: CAGradientLayer! let preferencesVC = PreferencesViewController() weak var menubarVCDelegate: MenubarViewControllerDelegate? - override func loadView() { self.view = boxView.view } From a9be17d376b35509f42d855848a801301779b297 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 23 Aug 2023 03:06:06 +0900 Subject: [PATCH 05/33] =?UTF-8?q?chore:=20box=20=ED=94=84=EB=A1=A0?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=B0=ED=8F=AC=EA=B0=80=20https=EA=B0=80=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=B4=EC=A7=90=EC=9C=BC=EB=A1=9C=EC=8D=A8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/URL/URLModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift index 014f62c..205a202 100644 --- a/Box42/WebView/URL/URLModel.swift +++ b/Box42/WebView/URL/URLModel.swift @@ -26,7 +26,7 @@ struct URLModels { // Network logic api call 날려서 받아올 것. let URLstring: [nameUrl] = [ - ("home", "http://42box.kr/"), + ("home", "https://42box.kr/"), ("23Coaltheme", "https://42box.github.io/front-end/"), // ("home", "http://127.0.0.1:3000/"), ("Box 42", "https://42box.github.io/front-end/#/box"), From 4992e50c7e3aa367a5f1f5e0af13ab10a2820f13 Mon Sep 17 00:00:00 2001 From: DaSol Kim Date: Wed, 23 Aug 2023 22:02:04 +0900 Subject: [PATCH 06/33] refactor: refactoring to NSTable with NSbuttons. (#71) --- .../Box/BoxBaseContainerViewController.swift | 5 + Box42/Box/View/BoxButtonViewGroup.swift | 223 +++++++++++++++++- Box42/Box/View/BoxContentsViewGroup.swift | 2 +- Box42/Window/BoxWindowController.swift | 1 - 4 files changed, 226 insertions(+), 5 deletions(-) diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 538078f..92c29d6 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -18,19 +18,24 @@ class BoxBaseContainerViewController: NSViewController { override func loadView() { self.view = NSView() +// self.view.wantsLayer = true +// self.view.layer?.backgroundColor = NSColor.red.cgColor self.view.addSubview(splitView) splitView.delegate = self buttonGroup = BoxButtonViewGroupInit() + leftContainerInit() viewInit() } func BoxButtonViewGroupInit() -> BoxButtonViewGroup { + let buttonGroup = BoxButtonViewGroup { sender in self.clickBtn(sender: sender) } + return buttonGroup } diff --git a/Box42/Box/View/BoxButtonViewGroup.swift b/Box42/Box/View/BoxButtonViewGroup.swift index 44a2299..c115950 100644 --- a/Box42/Box/View/BoxButtonViewGroup.swift +++ b/Box42/Box/View/BoxButtonViewGroup.swift @@ -8,6 +8,12 @@ import Cocoa import SnapKit +class CustomTableCellView: NSTableCellView { + var button: NSButton! + var deleteButton: NSButton! + var rowIndex: Int! +} + class BoxButtonViewGroup: NSView { var boxVM: WebViewModel! = WebViewModel() var pinSwitch : NSSwitch = NSSwitch() @@ -15,10 +21,99 @@ class BoxButtonViewGroup: NSView { var lastAddedButton: NSView? var loginInfo: NSView? + let tableView: NSTableView = { + let tableView = NSTableView() + tableView.autoresizingMask = [.width, .height] + tableView.headerView = nil + + let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("column1")) + column.title = "" + column.width = tableView.frame.size.width + column.resizingMask = .autoresizingMask + + tableView.addTableColumn(column) + + return tableView + }() + + let scrollView: NSScrollView = { + let scrollView = NSScrollView() + scrollView.borderType = .bezelBorder + return scrollView + }() + + private var isDeleteButtonsVisible: Bool = false + let toggleDeleteButton: NSButton = { + let button = NSButton(title: "-", target: nil, action: nil) + button.bezelStyle = .rounded + return button + }() + + @objc func toggleDeleteButtons() { + print("toggleDeleteButtons") + isDeleteButtonsVisible.toggle() + + let numberOfRows = tableView.numberOfRows + for row in 0.. Void) { + print("init") self.clickAction = clickAction super.init(frame: BoxSizeManager.shared.buttonGroupSizeNSRect) - setupButtons() + // setupButtons() + + for item in boxVM.webViewURL.URLstring { + buttonArray.append(item.name) + } + + scrollView.documentView = tableView + super.addSubview(scrollView) + scrollView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + tableView.dataSource = self + tableView.delegate = self + tableView.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) + + super.addSubview(toggleDeleteButton) + toggleDeleteButton.target = self + toggleDeleteButton.action = #selector(toggleDeleteButtons) + toggleDeleteButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(0) + } + + super.addSubview(addButton) + addButton.target = self + addButton.action = #selector(addCell) + addButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalTo(toggleDeleteButton.snp.top).offset(-10) + + } + } + + @objc func addCell() { + buttonArray.append("New Cell") // 'New Cell'은 신규 셀의 이름입니다. 필요에 따라 변경하십시오. + tableView.reloadData() } required init?(coder: NSCoder) { @@ -33,11 +128,12 @@ class BoxButtonViewGroup: NSView { for subview in self.subviews { subview.removeFromSuperview() } - + for (name, _) in boxVM.webViewURL.URLstring { self.createButton(name) } } + @objc private func clickBtn(sender: NSButton) { clickAction?(sender) } @@ -69,7 +165,7 @@ class BoxButtonViewGroup: NSView { button.font = NSFont.systemFont(ofSize: fontSize) button.setButtonType(.momentaryLight) button.translatesAutoresizingMaskIntoConstraints = false - + button.snp.makeConstraints { make in make.centerX.equalToSuperview() make.leading.equalToSuperview().offset(10) @@ -90,3 +186,124 @@ class BoxButtonViewGroup: NSView { lastAddedButton = button } } + +//NSTableViewDelegate +extension BoxButtonViewGroup: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + return buttonArray.count + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + let cellView = CustomTableCellView() + cellView.layer?.backgroundColor = NSColor.red.cgColor + cellView.rowIndex = row + + let button = NSButton(title: buttonArray[row], target: self, action: #selector(buttonClicked(_:))) + button.tag = row + cellView.addSubview(button) + + let fontSize: CGFloat = 16.0 + button.font = NSFont.systemFont(ofSize: fontSize) + button.setButtonType(.momentaryLight) + button.bezelStyle = .shadowlessSquare + + button.wantsLayer = true + button.layer?.borderWidth = 0 + button.layer?.cornerRadius = 10 + button.layer?.backgroundColor = NSColor.orange.cgColor + + button.snp.makeConstraints { make in + make.width.equalTo(100) + make.height.equalTo(50) + make.top.bottom.equalToSuperview().inset(5) + } + + let deleteButton = NSButton(title: "삭제", target: self, action: #selector(deleteButtonClicked(_:))) + deleteButton.tag = row + deleteButton.bezelStyle = .shadowlessSquare + deleteButton.wantsLayer = true + deleteButton.layer?.borderWidth = 0 + deleteButton.layer?.cornerRadius = 10 + deleteButton.layer?.backgroundColor = NSColor.red.cgColor + + cellView.addSubview(deleteButton) + deleteButton.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-5) + make.top.bottom.equalToSuperview().inset(5) + } + cellView.deleteButton = deleteButton + cellView.deleteButton.isHidden = !isDeleteButtonsVisible + + return cellView + } + + + @objc func deleteButtonClicked(_ sender: NSButton) { + let row = sender.tag + print("Delete button clicked in row: \(row)") + + // 데이터 목록에서 항목 제거 + buttonArray.remove(at: row) + tableView.reloadData() + // 테이블 뷰에서 행 제거 및 셀 인덱스 업데이트 + tableView.removeRows(at: IndexSet(integer: row), withAnimation: .effectFade) + for (_, subview) in tableView.subviews.enumerated() { + guard let cellView = subview as? CustomTableCellView else { + continue + } + + cellView.rowIndex = tableView.row(for: cellView) + cellView.button.tag = cellView.rowIndex + cellView.deleteButton.tag = cellView.rowIndex + + cellView.button.title = buttonArray[cellView.rowIndex] + } + } + + + func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { + return 40.0 + } + + @objc func buttonClicked(_ sender: NSButton) { + let row = sender.tag + print("Button clicked in row: \(row)") + } + + // Drag and Drop methods + func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? { + let pasteboardItem = NSPasteboardItem() + pasteboardItem.setString(String(row), forType: .string) + return pasteboardItem + } + + func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { + if dropOperation == .above { + return .move + } else { + return [] + } + } + + func tableView(_ aTableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool { + guard let str = info.draggingPasteboard.string(forType: .string), let from = Int(str) else { + return false + } + + let to = (from < row) ? row - 1 : row + let item = buttonArray[from] + buttonArray.remove(at: from) + buttonArray.insert(item, at: to) + tableView.reloadData() + + for (_, subview) in tableView.subviews.enumerated() { + guard let cellView = subview as? CustomTableCellView else { + continue + } + + cellView.button.title = buttonArray[cellView.rowIndex] + } + + return true + } +} diff --git a/Box42/Box/View/BoxContentsViewGroup.swift b/Box42/Box/View/BoxContentsViewGroup.swift index 215d0ce..596a5d1 100644 --- a/Box42/Box/View/BoxContentsViewGroup.swift +++ b/Box42/Box/View/BoxContentsViewGroup.swift @@ -22,7 +22,7 @@ class BoxContentsViewGroup: NSView { self.wantsLayer = true self.addSubview(webVC!.view) - + webVC?.view.translatesAutoresizingMaskIntoConstraints = false webVC?.view.snp.makeConstraints { make in make.edges.equalTo(self) diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index dc69045..fde61fa 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -8,7 +8,6 @@ import Cocoa class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelegate { - override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect let styleMask: NSWindow.StyleMask = [.resizable, .closable, .miniaturizable, .fullSizeContentView, .titled] From 0eca2eafb39ba2cd286a8947916c3c76d0787b43 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Thu, 24 Aug 2023 21:56:06 +0900 Subject: [PATCH 07/33] =?UTF-8?q?fix:=20WebView=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=EC=99=84=EC=84=B1=EC=8B=9C=20layer=EA=B0=80=20=EC=82=AC?= =?UTF-8?q?=EB=9D=BC=EC=A7=80=EB=8D=98=20=ED=98=84=EC=83=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Extensions/NSColor.swift | 30 ++++++++++++++++++++++++++++++ Box42/Main/BoxViewController.swift | 16 ++-------------- 2 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 Box42/Extensions/NSColor.swift diff --git a/Box42/Extensions/NSColor.swift b/Box42/Extensions/NSColor.swift new file mode 100644 index 0000000..8360c15 --- /dev/null +++ b/Box42/Extensions/NSColor.swift @@ -0,0 +1,30 @@ +// +// NSColor.swift +// Box42 +// +// Created by Chanhee Kim on 8/24/23. +// + +import AppKit + +extension NSColor { + convenience init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + + self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255) + } +} diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index 551ba31..5a3db90 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -24,19 +24,7 @@ class BoxViewController: NSViewController { menubarVCDelegate = (NSApplication.shared.delegate as? AppDelegate)?.menubarController self.view.wantsLayer = true - setupGradientLayer() - - NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChange), name: NSWindow.didResizeNotification, object: self.view.window) - } - - func setupGradientLayer() { - gradientLayer = CAGradientLayer() - gradientLayer.frame = self.view.bounds - let startingColor = NSColor(red: 1.0, green: 0.804, blue: 0.0, alpha: 0.9).cgColor - let endingColor = NSColor(red: 1.0, green: 0.447, blue: 0.0, alpha: 0.7).cgColor - gradientLayer.colors = [startingColor, endingColor] - - self.view.layer?.addSublayer(gradientLayer) + self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor } @objc func boundsDidChange(notification: NSNotification) { @@ -52,7 +40,7 @@ class BoxViewController: NSViewController { @objc func pin(_ sender: NSSwitch) { - StateManager.shared.setToggleIsPin() + StateManager.shared.togglePin() print(sender.state) } From 472ddfc60e12f587110dfe857729bcbe7ca9b3c0 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Thu, 24 Aug 2023 22:35:18 +0900 Subject: [PATCH 08/33] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=A1=B0=EB=A5=BC?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{NSColor.swift => HexValue+NSColor.swift} | 0 .../BoxBaseContainerViewController.swift | 50 +++++++++++++------ Box42/Main/BoxViewController.swift | 50 ------------------- ...Down+BoxBaseContainerViewController.swift} | 2 +- Box42/Menubar/MenubarViewController.swift | 14 +++--- Box42/{Box => }/View/BoxBaseSplitView.swift | 0 Box42/{Box => }/View/BoxButtonViewGroup.swift | 0 .../{Box => }/View/BoxContentsViewGroup.swift | 1 - Box42/Window/BoxWindowController.swift | 6 +-- 9 files changed, 45 insertions(+), 78 deletions(-) rename Box42/Extensions/{NSColor.swift => HexValue+NSColor.swift} (100%) rename Box42/{Box => Main}/BoxBaseContainerViewController.swift (78%) delete mode 100644 Box42/Main/BoxViewController.swift rename Box42/Main/{keyDown+BoxViewController.swift => keyDown+BoxBaseContainerViewController.swift} (95%) rename Box42/{Box => }/View/BoxBaseSplitView.swift (100%) rename Box42/{Box => }/View/BoxButtonViewGroup.swift (100%) rename Box42/{Box => }/View/BoxContentsViewGroup.swift (97%) diff --git a/Box42/Extensions/NSColor.swift b/Box42/Extensions/HexValue+NSColor.swift similarity index 100% rename from Box42/Extensions/NSColor.swift rename to Box42/Extensions/HexValue+NSColor.swift diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift similarity index 78% rename from Box42/Box/BoxBaseContainerViewController.swift rename to Box42/Main/BoxBaseContainerViewController.swift index 836ca15..e07a11e 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -16,21 +16,24 @@ class BoxBaseContainerViewController: NSViewController { let windowViewGroup: WindowButtonViewController = WindowButtonViewController() var buttonGroup: BoxButtonViewGroup! var leftContainer: MovableContainerView! - + weak var menubarVCDelegate: MenubarViewControllerDelegate? // extension + override func loadView() { self.view = NSView() -// self.view.wantsLayer = true -// self.view.layer?.backgroundColor = NSColor.red.cgColor self.view.addSubview(splitView) splitView.delegate = self buttonGroup = BoxButtonViewGroupInit() - leftContainerInit() viewInit() } + override func viewDidLoad() { + self.view.wantsLayer = true + self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor + } + func BoxButtonViewGroupInit() -> BoxButtonViewGroup { let buttonGroup = BoxButtonViewGroup { sender in @@ -40,19 +43,28 @@ class BoxBaseContainerViewController: NSViewController { return buttonGroup } - func clickBtn(sender: NSButton) { - guard let clickCount = NSApp.currentEvent?.clickCount else { return } - if clickCount == 2 { - WebViewManager.shared.list[sender.title]!.reload() - print("Dobule Click") - } else if clickCount > 2 { - if let currentURL = WebViewManager.shared.hostingWebView?.url { - NSWorkspace.shared.open(currentURL) + func clickBtn(sender: Any?) { + if let button = sender as? NSButton { + guard let clickCount = NSApp.currentEvent?.clickCount else { return } + if clickCount == 2 { + WebViewManager.shared.list[button.title]!.reload() + print("Dobule Click") + } else if clickCount > 2 { + if let currentURL = WebViewManager.shared.hostingWebView?.url { + NSWorkspace.shared.open(currentURL) + } + print("Triple Click") + } else if clickCount < 2 { + contentGroup.removeAllSubviews() + contentGroup.showWebviews(button) + } + } else { + if let str = sender as? String { + if str == "box" { + contentGroup.removeAllSubviews() + print("box inside") + } } - print("Triple Click") - } else if clickCount < 2 { - contentGroup.removeAllSubviews() - contentGroup.showWebviews(sender) } } @@ -140,3 +152,9 @@ extension BoxBaseContainerViewController: NSSplitViewDelegate { contentGroup.frame = NSRect(x: leftWidth + dividerThickness, y: 0, width: contentWidth, height: splitView.bounds.height) } } + +extension BoxBaseContainerViewController: BoxFunctionViewControllerDelegate { + func didTapBoxButton() { + clickBtn(sender: "box") // 여기에 적절한 sender (NSButton) 전달) + } +} diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift deleted file mode 100644 index 5a3db90..0000000 --- a/Box42/Main/BoxViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// BoxViewController.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import AppKit -import WebKit - -class BoxViewController: NSViewController { - var boxView: BoxBaseContainerViewController = BoxBaseContainerViewController() - var gradientLayer: CAGradientLayer! - let preferencesVC = PreferencesViewController() - weak var menubarVCDelegate: MenubarViewControllerDelegate? - - override func loadView() { - self.view = boxView.view - } - - override func viewDidLoad() { - super.viewDidLoad() - - menubarVCDelegate = (NSApplication.shared.delegate as? AppDelegate)?.menubarController - - self.view.wantsLayer = true - self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor - } - - @objc func boundsDidChange(notification: NSNotification) { - if let window = notification.object as? NSWindow { - gradientLayer.frame = window.contentView!.bounds - } - } - - @objc - func doubleClickBtn(sender: NSButton) { - WebViewManager.shared.list[sender.title]!.reload() - } - - @objc - func pin(_ sender: NSSwitch) { - StateManager.shared.togglePin() - print(sender.state) - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - print(message.name) - } -} diff --git a/Box42/Main/keyDown+BoxViewController.swift b/Box42/Main/keyDown+BoxBaseContainerViewController.swift similarity index 95% rename from Box42/Main/keyDown+BoxViewController.swift rename to Box42/Main/keyDown+BoxBaseContainerViewController.swift index 63b89e2..f16fcfc 100644 --- a/Box42/Main/keyDown+BoxViewController.swift +++ b/Box42/Main/keyDown+BoxBaseContainerViewController.swift @@ -7,7 +7,7 @@ import AppKit -extension BoxViewController { +extension BoxBaseContainerViewController { override func keyDown(with event: NSEvent) { print(event.keyCode) if event.keyCode == 1 { diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 2cb1a3f..7a8a719 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -8,7 +8,7 @@ import Foundation import AppKit -class MenubarViewController: NSWorkspace { +class MenubarViewController: NSViewController { var popover = NSPopover() var statusBarVM = StatusBarViewModel() lazy var eventMonitor: EventMonitor = self.setupEventMonitor() @@ -56,14 +56,14 @@ class MenubarViewController: NSWorkspace { } func popoverCoentViewInit() { - let boxViewController = BoxViewController(nibName: nil, bundle: nil) + let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) popover.contentViewController = boxViewController } func setupEventMonitor() -> EventMonitor { return EventMonitor(mask: [.leftMouseDown, .rightMouseDown, .otherMouseDown]) { [weak self] event in if let strongSelf = self, strongSelf.popover.isShown { - if StateManager.shared.getIsPin() == false && event?.buttonNumber != 2 { + if StateManager.shared.pin == false && event?.buttonNumber != 2 { strongSelf.closePopover(sender: event) } } else if let strongSelf = self, !strongSelf.popover.isShown { @@ -99,8 +99,8 @@ class MenubarViewController: NSWorkspace { extension MenubarViewController: MenubarViewControllerDelegate { func toggleWindow(sender: Any?) { - StateManager.shared.setToggleIsShowWindow() - if StateManager.shared.getIsShowWindow() == false { + StateManager.shared.toggleShowWindow() + if StateManager.shared.showWindow == false { if let window = boxWindowController?.window { if window.isVisible { window.orderOut(sender) @@ -113,12 +113,12 @@ extension MenubarViewController: MenubarViewControllerDelegate { } if let button = statusBarVM.statusBar.statusItem.button, let window = boxWindowController?.window { - if StateManager.shared.getIsShowFirstWindow() == false { + if StateManager.shared.showFirstWindow == false { let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect let desiredPosition = NSPoint(x: buttonFrame.origin.x - (BoxSizeManager.shared.size.width / 2) - 10, y: buttonFrame.origin.y - window.frame.height) window.setFrameOrigin(desiredPosition) - StateManager.shared.setToggleIsShowFirstWindow() + StateManager.shared.toggleShowFirstWindow() } window.level = .floating } diff --git a/Box42/Box/View/BoxBaseSplitView.swift b/Box42/View/BoxBaseSplitView.swift similarity index 100% rename from Box42/Box/View/BoxBaseSplitView.swift rename to Box42/View/BoxBaseSplitView.swift diff --git a/Box42/Box/View/BoxButtonViewGroup.swift b/Box42/View/BoxButtonViewGroup.swift similarity index 100% rename from Box42/Box/View/BoxButtonViewGroup.swift rename to Box42/View/BoxButtonViewGroup.swift diff --git a/Box42/Box/View/BoxContentsViewGroup.swift b/Box42/View/BoxContentsViewGroup.swift similarity index 97% rename from Box42/Box/View/BoxContentsViewGroup.swift rename to Box42/View/BoxContentsViewGroup.swift index 596a5d1..1eb1ee5 100644 --- a/Box42/Box/View/BoxContentsViewGroup.swift +++ b/Box42/View/BoxContentsViewGroup.swift @@ -69,7 +69,6 @@ class BoxContentsViewGroup: NSView { } currentWebview.viewDidMoveToSuperview() - currentWebview.becomeFirstResponder() } } diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index 063dd96..38165ca 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -21,14 +21,14 @@ class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelega windowInstance.backgroundColor = .clear windowInstance.isMovableByWindowBackground = true - let boxViewController = BoxViewController(nibName: nil, bundle: nil) + let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController super.init(window: windowInstance) windowInstance.delegate = self -// setupToolbar() + setupToolbar() } required init?(coder: NSCoder) { @@ -39,7 +39,7 @@ class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelega extension BoxWindowController { func windowShouldClose(_ sender: NSWindow) -> Bool { // NSApplication.shared.terminate(self) - StateManager.shared.setToggleIsShowWindow() + StateManager.shared.toggleShowWindow() return true } } From 621bedff08699377f0a9405d468d123b6f0d949b Mon Sep 17 00:00:00 2001 From: chanhihi Date: Thu, 24 Aug 2023 22:36:31 +0900 Subject: [PATCH 09/33] =?UTF-8?q?fix:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=A7=B5=ED=95=91=EC=9D=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FunctionButton/BoxFunctionViewController.swift | 7 +++++++ Box42/Toolbar/View/BoxToolbarViewGroup.swift | 13 ++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Box42/FunctionButton/BoxFunctionViewController.swift b/Box42/FunctionButton/BoxFunctionViewController.swift index a2a482e..42e3396 100644 --- a/Box42/FunctionButton/BoxFunctionViewController.swift +++ b/Box42/FunctionButton/BoxFunctionViewController.swift @@ -36,7 +36,14 @@ class BoxFunctionViewController: NSViewController { NSApplication.shared.terminate(self) } + weak var delegate: BoxFunctionViewControllerDelegate? + func box() { print("box") + delegate?.didTapBoxButton() } } + +protocol BoxFunctionViewControllerDelegate: AnyObject { + func didTapBoxButton() +} diff --git a/Box42/Toolbar/View/BoxToolbarViewGroup.swift b/Box42/Toolbar/View/BoxToolbarViewGroup.swift index 3d63053..6495f30 100644 --- a/Box42/Toolbar/View/BoxToolbarViewGroup.swift +++ b/Box42/Toolbar/View/BoxToolbarViewGroup.swift @@ -10,11 +10,11 @@ import SnapKit class BoxToolbarViewGroup: NSView { var displayURL = DisplayURLInToolbar() - lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.goBack?() }) - lazy var goBackButton: GoBackInToolbar = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.goFoward?()} ) - lazy var goForwardButton: GoForwardInToolbar = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.reloadPage?() }) - lazy var reloadPageButton: ReloadPageViaToolbar = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: { self.goToHome?() }) - lazy var goHomePageViaButton: GoHomePageViaToolbar = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: { self.sidebar?() }) + lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.sidebar?() }) + lazy var goBackButton: GoBackInToolbar = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.goBack?() }) + lazy var goForwardButton: GoForwardInToolbar = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.goFoward?()} ) + lazy var reloadPageButton: ReloadPageViaToolbar = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: { self.reloadPage?() }) + lazy var goHomePageViaButton: GoHomePageViaToolbar = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: { self.goToHome?() }) var goBack: (() -> Void)? var goFoward: (() -> Void)? @@ -50,7 +50,7 @@ class BoxToolbarViewGroup: NSView { } sidebarLeading.snp.makeConstraints { make in - make.top.equalTo(displayURL).offset(10) + make.top.equalTo(displayURL.snp.bottom).offset(10) make.bottom.equalToSuperview() make.left.equalToSuperview() make.width.equalTo(goBackButton) @@ -79,6 +79,5 @@ class BoxToolbarViewGroup: NSView { make.left.equalTo(reloadPageButton.snp.right).offset(10) make.right.equalToSuperview() } - } } From 606b27b9ce97743b0a3c1537600ecebaa4229d35 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Thu, 24 Aug 2023 22:36:52 +0900 Subject: [PATCH 10/33] =?UTF-8?q?build:=20=F0=9F=9B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 57 ++++++++++++++++++++---------- Box42/Resources/Box42.entitlements | 6 +++- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 54be299..0d9fb62 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -38,7 +38,6 @@ DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */; }; DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */; }; DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */; }; - DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */; }; DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */; }; DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */; }; DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A302A8BD68F00A88DD8 /* Double.swift */; }; @@ -47,13 +46,19 @@ DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */; }; DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE24E63A2A8FE93900E29F5D /* NSImage.swift */; }; DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; + DE3FF3672A978A37009C88EF /* HexValue+NSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3662A978A37009C88EF /* HexValue+NSColor.swift */; }; + DE3FF36B2A978A57009C88EF /* WindowButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */; }; + DE3FF3742A978AB8009C88EF /* WindowMaximizeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */; }; + DE3FF3752A978AB8009C88EF /* WindowViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */; }; + DE3FF3762A978AB8009C88EF /* WindowCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */; }; + DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */; }; DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4407F92A923E860091937A /* BoxFunctionViewController.swift */; }; DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */; }; DE4408022A923EB60091937A /* PinButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408012A923EB60091937A /* PinButtonView.swift */; }; DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408042A923EC00091937A /* QuitButtonView.swift */; }; DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408072A9240300091937A /* BoxFunctionButtonView.swift */; }; DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44080B2A924B520091937A /* BoxFunctionViewGroup.swift */; }; - DE4408152A92750D0091937A /* keyDown+BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408142A92750D0091937A /* keyDown+BoxViewController.swift */; }; + DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */; }; DE44081D2A928F760091937A /* TopDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44081C2A928F760091937A /* TopDivider.swift */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; @@ -100,10 +105,9 @@ DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = importMacOSInfo.sh; sourceTree = ""; }; DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = exportMacOSInfo.sh; sourceTree = ""; }; DE1F1A132A8B506600A88DD8 /* keyMapping.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = keyMapping.sh; sourceTree = ""; }; - DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxBaseContainerViewController.swift; path = Box/BoxBaseContainerViewController.swift; sourceTree = ""; }; + DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxBaseContainerViewController.swift; path = Main/BoxBaseContainerViewController.swift; sourceTree = ""; }; DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxContentsViewGroup.swift; sourceTree = ""; }; DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxButtonViewGroup.swift; sourceTree = ""; }; - DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewController.swift; path = Main/BoxViewController.swift; sourceTree = ""; }; DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxSizeManager.swift; sourceTree = ""; }; DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; DE1F1A302A8BD68F00A88DD8 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = ""; }; @@ -112,13 +116,19 @@ DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxBaseSplitView.swift; sourceTree = ""; }; DE24E63A2A8FE93900E29F5D /* NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSImage.swift; sourceTree = ""; }; DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.swift; sourceTree = ""; }; + DE3FF3662A978A37009C88EF /* HexValue+NSColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HexValue+NSColor.swift"; sourceTree = ""; }; + DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowButtonViewController.swift; sourceTree = ""; }; + DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowMaximizeButton.swift; sourceTree = ""; }; + DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowViewGroup.swift; sourceTree = ""; }; + DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowCloseButton.swift; sourceTree = ""; }; + DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowMinimizeButton.swift; sourceTree = ""; }; DE4407F92A923E860091937A /* BoxFunctionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionViewController.swift; sourceTree = ""; }; DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceButtonView.swift; sourceTree = ""; }; DE4408012A923EB60091937A /* PinButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinButtonView.swift; sourceTree = ""; }; DE4408042A923EC00091937A /* QuitButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuitButtonView.swift; sourceTree = ""; }; DE4408072A9240300091937A /* BoxFunctionButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionButtonView.swift; sourceTree = ""; }; DE44080B2A924B520091937A /* BoxFunctionViewGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionViewGroup.swift; sourceTree = ""; }; - DE4408142A92750D0091937A /* keyDown+BoxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "keyDown+BoxViewController.swift"; path = "Main/keyDown+BoxViewController.swift"; sourceTree = ""; }; + DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "keyDown+BoxBaseContainerViewController.swift"; path = "Main/keyDown+BoxBaseContainerViewController.swift"; sourceTree = ""; }; DE44081C2A928F760091937A /* TopDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopDivider.swift; sourceTree = ""; }; DE77BA502A82580400713683 /* MenubarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarViewModel.swift; sourceTree = ""; }; DE77BA552A82637900713683 /* StateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateManager.swift; sourceTree = ""; }; @@ -167,19 +177,17 @@ DE018BB12A5099F900FF0AA3 /* Box42 */ = { isa = PBXGroup; children = ( - DE0A916B2A8E7DC700D1D6F1 /* UI */, - DE1F1A202A8B50CA00A88DD8 /* Main */, + DE77BA542A82636500713683 /* Shared */, DEF749302A85655E00D987C8 /* Extensions */, + DE1F1A202A8B50CA00A88DD8 /* Main */, DEB862E82A853F6800278FCD /* Window */, DEB862D22A8511D600278FCD /* Scripts */, - DE77BA542A82636500713683 /* Shared */, DE874F512A591EC600FC3B77 /* Preferences */, DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, DE0A917D2A8F864300D1D6F1 /* Toolbar */, DE4407F82A923E5B0091937A /* FunctionButton */, - DE1F1A182A8B50BB00A88DD8 /* Box */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; @@ -279,22 +287,26 @@ name = Frameworks; sourceTree = ""; }; - DE1F1A182A8B50BB00A88DD8 /* Box */ = { + DE1F1A202A8B50CA00A88DD8 /* Main */ = { isa = PBXGroup; children = ( + DE0A916B2A8E7DC700D1D6F1 /* UI */, DE4408202A9297EE0091937A /* View */, DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, + DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */, ); - name = Box; + name = Main; sourceTree = ""; }; - DE1F1A202A8B50CA00A88DD8 /* Main */ = { + DE3FF36F2A978A6E009C88EF /* View */ = { isa = PBXGroup; children = ( - DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */, - DE4408142A92750D0091937A /* keyDown+BoxViewController.swift */, + DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */, + DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */, + DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */, + DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */, ); - name = Main; + path = View; sourceTree = ""; }; DE4407F82A923E5B0091937A /* FunctionButton */ = { @@ -326,8 +338,7 @@ DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); - name = View; - path = Box/View; + path = View; sourceTree = ""; }; DE77BA542A82636500713683 /* Shared */ = { @@ -377,6 +388,8 @@ DEB862E82A853F6800278FCD /* Window */ = { isa = PBXGroup; children = ( + DE3FF36F2A978A6E009C88EF /* View */, + DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */, DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, ); path = Window; @@ -385,6 +398,7 @@ DEF749302A85655E00D987C8 /* Extensions */ = { isa = PBXGroup; children = ( + DE3FF3662A978A37009C88EF /* HexValue+NSColor.swift */, DE874F5E2A5935CC00FC3B77 /* String.swift */, DEF749312A85657600D987C8 /* NSScreen.swift */, DE1F1A302A8BD68F00A88DD8 /* Double.swift */, @@ -473,13 +487,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DE3FF3752A978AB8009C88EF /* WindowViewGroup.swift in Sources */, DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */, DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, - DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, + DE3FF3742A978AB8009C88EF /* WindowMaximizeButton.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, @@ -501,9 +516,11 @@ DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, + DE3FF3762A978AB8009C88EF /* WindowCloseButton.swift in Sources */, + DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */, DE4408022A923EB60091937A /* PinButtonView.swift in Sources */, DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, - DE4408152A92750D0091937A /* keyDown+BoxViewController.swift in Sources */, + DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */, DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */, @@ -511,6 +528,7 @@ DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, DE0A918D2A8F88BC00D1D6F1 /* GoBackInToolbar.swift in Sources */, DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, + DE3FF3672A978A37009C88EF /* HexValue+NSColor.swift in Sources */, DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, @@ -522,6 +540,7 @@ DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */, + DE3FF36B2A978A57009C88EF /* WindowButtonViewController.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE0A917F2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, diff --git a/Box42/Resources/Box42.entitlements b/Box42/Resources/Box42.entitlements index aa078cb..1b4b0b0 100644 --- a/Box42/Resources/Box42.entitlements +++ b/Box42/Resources/Box42.entitlements @@ -6,7 +6,11 @@ com.apple.security.automation.apple-events - com.apple.security.files.user-selected.read-only + com.apple.security.device.camera + + com.apple.security.files.downloads.read-write + + com.apple.security.files.user-selected.read-write com.apple.security.network.client From 2043bb03558a5c41d84d4a12855cb290e846f73a Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:13:51 +0900 Subject: [PATCH 11/33] =?UTF-8?q?feat:=20UI=EB=A5=BC=20=EC=9C=84=ED=95=9C?= =?UTF-8?q?=20Asset=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../42pack_icon/fox/Contents.json | 6 + .../fox/fox_page0.imageset/Contents.json | 20 ++ .../fox/fox_page0.imageset/fox0.png | Bin 0 -> 3944 bytes .../fox/fox_page1.imageset/Contents.json | 20 ++ .../fox/fox_page1.imageset/fox1.png | Bin 0 -> 3950 bytes .../fox/fox_page2.imageset/Contents.json | 20 ++ .../fox/fox_page2.imageset/fox2.png | Bin 0 -> 3946 bytes .../fox/fox_page3.imageset/Contents.json | 20 ++ .../fox/fox_page3.imageset/fox3.png | Bin 0 -> 3990 bytes .../fox/fox_page4.imageset/Contents.json | 20 ++ .../fox/fox_page4.imageset/fox4.png | Bin 0 -> 3900 bytes .../Contents.json | 0 .../arrow.left@2x.png | Bin .../Assets.xcassets/uibuttons/Contents.json | 6 + .../Assets.xcassets/uibuttons/Ellipse 1.png | Bin 0 -> 570 bytes .../arrow-left.imageset/Contents.json | 21 ++ .../arrow-left.imageset/arrow-left.png | Bin 0 -> 402 bytes .../arrow-right.imageset/Contents.json | 21 ++ .../arrow-right.imageset/arrow-right.png | Bin 0 -> 399 bytes .../uibuttons/circle.imageset/Contents.json | 21 ++ .../uibuttons/circle.imageset/Ellipse 1.png | Bin 0 -> 570 bytes .../rotate-right.imageset/Contents.json | 21 ++ .../rotate-right.imageset/rotate-right.png | Bin 0 -> 639 bytes .../toggle-off.imageset/Contents.json | 21 ++ .../toggle-off.imageset/toggle-off.png | Bin 0 -> 676 bytes .../toggle-on.imageset/Contents.json | 21 ++ .../toggle-on.imageset/toggle-on.png | Bin 0 -> 672 bytes Box42/View/BoxButtonViewGroup.swift | 309 ------------------ Box42/Window/BoxWindowController.swift | 136 -------- Box42/Window/View/WindowCloseButton.swift | 31 -- Box42/Window/View/WindowMaximizeButton.swift | 31 -- Box42/Window/View/WindowMinimizeButton.swift | 31 -- Box42/Window/View/WindowViewGroup.swift | 56 ---- Box42/Window/WindowButtonViewController.swift | 36 -- 34 files changed, 238 insertions(+), 630 deletions(-) create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/fox0.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/fox1.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/fox2.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/fox3.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/fox4.png rename Box42/Resources/Assets.xcassets/Icons/{arrow.left.imageset => _arrow.left.imageset}/Contents.json (100%) rename Box42/Resources/Assets.xcassets/Icons/{arrow.left.imageset => _arrow.left.imageset}/arrow.left@2x.png (100%) create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Ellipse 1.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/arrow-left.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/arrow-right.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Ellipse 1.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/rotate-right.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/toggle-off.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/toggle-on.png delete mode 100644 Box42/View/BoxButtonViewGroup.swift delete mode 100644 Box42/Window/BoxWindowController.swift delete mode 100644 Box42/Window/View/WindowCloseButton.swift delete mode 100644 Box42/Window/View/WindowMaximizeButton.swift delete mode 100644 Box42/Window/View/WindowMinimizeButton.swift delete mode 100644 Box42/Window/View/WindowViewGroup.swift delete mode 100644 Box42/Window/WindowButtonViewController.swift diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/Contents.json new file mode 100644 index 0000000..64bcd2c --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "fox0.png", + "idiom" : "mac", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/fox0.png b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/fox0.png new file mode 100644 index 0000000000000000000000000000000000000000..0892874e263d4aece136bfac2d934cdb392569c4 GIT binary patch literal 3944 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%0Dy!50Qvv` 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%0Dy!50Qvv` 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600eePL_t(&f$f=ZXq9yo$3Mrl zW|5VYe;5^&)Qd>M7v(4+sjwn3%LHk?=|z$gvLc&AD zuwueyHVgPw((w4WR9%b^HnSPPdSDUIEU9Ze9jg|?gl_@%0OtV@120MXYaD&63c`d} z0xtyZj{|KJaa)H8cL7U-_PxMzNxz$!X#zzylZ2UF1snn{49Ok^wn`ctAJ?jbJmICl zE?`QLd>zmZ^p4kgHnTcl2XH{rbE)+OgqHwaj3x~5CGZL!(0-IOl-6iDFthuC4&WHD zTGFlrV>Sb`B{hzc1%z+K&uvW!JzwC&_XCH4firQo&8!)CHuyOVd=9LU^hr$r?ZABC z5@4mIjskf=xE?2QP68hUoC3bZSN&^Xx1?MJe8z;C-3Yu7oE>UD3~ZLPHRxlKWM)qQ z8}XewNF3o{&`d@dfX7nDV-H1-5KZwKy<>2n--15anaDsa%O19%`}OdQd? z44_j|!Puzsa4zsXPP#UhM!X>reV->qJHCa_$0uoF30tLhV*Y&BOFEHn97T9UV0I_4 z7`OwtGH4zOK2w74Fu`d_*qmVq*as|=)DI;H=V4|wz#QOa;2Yp)eC3Dm;4l>rDD!~J z@vE&4zb4AvAz2~3`Z>G`TrEjs5{^P#1!ZPa@vXQ8xVLhDGetgXF9bfWh;SUtY(8FP zt;kGiIt<_ueh@ExKTA#6%q|7i;7>zy(|VX8a=;&WO4@`+?EX}Q&1^BS4VaOMi`iiS z_z2JU_XGPRorVNKD-J;wvoR|VGk}0zpcB|6>1b4^N`ux~pf#0y)j2u{^sER!f|rzGG)dZ$T6t-^58{6dU0WntBI(V@F&PnF0DOp-iN64kNqQ}{ z;$*gKfJWdRyo@~nY{)e6_%CCU@I=QX;fan(!V?{T0~cWU$u0V9RR91007*qoM6N<$ Ef}%1};{X5v literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/Contents.json new file mode 100644 index 0000000..533abef --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "fox3.png", + "idiom" : "mac", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/fox3.png b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/fox3.png new file mode 100644 index 0000000000000000000000000000000000000000..e15e2be4392683ec49db67a521070da37c90cc06 GIT binary patch literal 3990 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600g2*L_t(&f$iFV$lX;P2k_Tt z=3pj_da{>bH5jz`G$wfJ?DJi=kq@2d_U*&`P`?H z_W8lH566GrPk`!BurUK8iQuR0N9#hCPM9 z;Ro25WXtqS?FK^ySJfiifVbjsyl5U=zrweZe792zJH`QmtLkuU#9Gvte1FHqNp9`N zyzVhf@Riz89#`xPw&UC++a|PaD%ekORb7J1@xlptzm;VDgd9`Btl+9T7oW%LJK+5j z&Q5ZF2V9`4R^b!akmT;Fsx076tt6`IINXd^;20c+z1XdJ<|Uf*8bpjf`d23T__ziQ zHL_|+&%U*|A7>=lwGh$$JA6J?;2}-Oj^5u>I70K(FTojDgA;K=kLSM*T#(--IdN=t z!;Gvt20zCud$w)H$CBJP$1|mE;1fw6o^4-9q*YZ%;N>_Q7ij?r`|o)0t|S}Bo?!T# z_u=HeroZ6)BtM(k>Augy@J_rNk0e<)+c!yQSyhYiYEAUIAwza1S-#*2_RX_g+trl= zT@T^INq#gi{!)BWJC%>%lq5UoAeQbOog?u9d>Stu81lU&7gp6#+B>)sci_<^f1c+Y ztFZ~g7H?;7?w?>;&xVVzxYz#}-jw7XI!+#{YK6Ab=iwy#j`vm^tNDN#Jb@qLs|WMu zRdu=+46T@B*e^AIa|&M2*S;NRCiyE<%$BO^E}S`!p^xK&B)1RYSd?UMRc*ip_U+mz z4Ehk-LcA@>Zl)x-s+MZ8^^3=N?6M?Z8p5?6-{^gv>l*Awzo;K;&hs&*C-@HSeH|CK zVBPHTtGW;y4)V;w7U53q1npu9f~)Gy_~`@`|HL)gRrih#Oxmiw!;do^!FOxH$+HCy z;-n-`(!G~{gBB4zn{W@-%!Htw39hOWutmEIpJ~j9DyZqgluxe z{w1j`I4{Y=T?#%8cNv~lJyY0gpXkrw%U!?2n{ZZVgp*^pmdP!}rMR|h!Q1ef&Il*N z9{gMLDOcf}c(7~1n{oPx?x(R{EA+ibt94JBN%b3FTBT(xwrThIlUnV3^Hc(l5!cew zxI!z<{I+lGQQGle)B9Ye<=Eq3hbHhAEt^`bE$F{yuc2N%K0EIe0*~8pPG8f!a^han z{uUgK)%c87YC0JHfXkCyH!u69Ab1t-?Q7bF)OK;6@zZ>pN2WQSYXiBw-}ylmwrOU-Z6yKgoM1;Ch|5 zbNxB*rX+7)5Z@F_JZrTY)Qw60Ga=Wf@b!V__a(W0Y_3D)KLD!gGJJ8M`Q&kbv^!)3 wLsi{w|0>AX&hStZTzJ1$+rBo*1LJc153sif`|}XN$N&HU07*qoM6N<$f)O3B(f|Me literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/Contents.json new file mode 100644 index 0000000..018fb9c --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "fox4.png", + "idiom" : "mac", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/fox4.png b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/fox4.png new file mode 100644 index 0000000000000000000000000000000000000000..352f1859245446e16b7a96567c9f14601342b0e1 GIT binary patch literal 3900 zcmV-C55w?@P)f6 zXi@@54ZTQ_E-Enz5K6$103tR-RB%L5k){YTDBysjLy@r}iiH7DvFijGMAUI`6dRUF zWUU$Bym{}eS9UO(Z2>7`&z9wUXbV-Il#&6`Y8GKGQ04S2&F6MJnWNa;Ck|;8QE#r9r;7G||@X{|> z%+C|c55>;RS}qbKr-&IQTvLXPlM{>K&(BTgi^a?^4mXV>;xX8n8Ce|RasXz}{8imI52H3ZN4bfe_i~WlJ|C&UW9+{8AKoW!}eExnGFE2re(F+`iE_46#!l9 z0Z_aBhs|Iw0E)7{bq;-T9=d#9QpDmcXDh4R++0fmpKB>E=%LdZt9g$j;($`3&Zthxi`{{&gM}5&R^+h%b~yM9Zd3AWW9ETgVfL z1(`yIK=_}U_z%PWq}jQaiQ4!P(3V&Nr6C$XejWfQDiI(Fdt@un?|lo#M+5oIi_w{w zo%_#%{(V=tO#a9gB!7-$M?^BX5>d|Vn*3S!?g~$*UQipUPL&zMmg;!4Do9IA%up=Rh? z=qPj=x&RGBx1dpI68aT-2O}^EromdU5o`ssU{5#*j)WJ%$?!5bA1;Eoz?EiTr=n?cd`V|I)p<|3Oju?MT93~aB0<#&j8`F+Cg&D?-VWzQItUA^l>xvD zRIYI4MQ`g1<+DyrL=EogS06Xii({| zv`U^zjmmKqDIK93(F5q|^fLNk`gQs{RV`IdRle#b)i%{Ds;|}NsClUI)k@Ub)kf6b zsWa4l)YH_rsduU0(?DsMX@qO!YV6TCtMPOWZH~(v?wpc2hv(eZgf-1HBQ#fN?$aF5 zoYvCT^3%%Fs?s{6^;Da#?V+8jy+iwi_M{F~$4y6|vqR^k&SQoO!;_KDsATjprgSxR z{dFa}^}2()GkV5)QF?`X?Rxk03HmJkB>f%wz4}uIItC#I1qQ7Kw+-=zEW;GTU55RJ zuZ@h2VvIHzbs0S}Rx=JT&Npr~zH34@aW`3J(qMAU6l2OVO*7qXdf5y%vo}jIt1%lg zhs_<#1?IcWhb_<+P8LFo28$a^64R5J!)#@aTGB0pEekEXET35!SjAgyv+B3{Xl-wu zZrx~o$A)4PXj5p@WAm%6nJw40#`fA=@?77!tLJvleQsxN$G6*KchjC~A7a13zSsVP zgQJ7Uq0M2^(ZDg$vDWbhi^d9LZDyT!LOXdmt#&%*^w!zIS?qk+`4<X~g?%56 z2@eae34a)26HyS+zks@6$%2*zuOhu7%OdYYnM6sVdZQJi6QY}=U&naIl*dS8tzuWk zUW(I*6U24LW8oFzvR(TOpM zEs5_rp_~TJ^wNN(wM(bCZ0;`Z6P^ce2XB(^$}i_nB)KM)Cp}7bP2Qe7nc|*Ok@8f) z7E}wKr~0SXrM^xJP1~RLDLp2=Jp-4Km~m7{5vB?IGPN`FGKaIwvx>8%%bb_(Ts9>N z5;bK**^9Ef#WdN^)PTf9vR*Qp{o-l7 zTcBI8wqSIn=gRt3(5j`YdRObOE?Pal#&6AmwS={4Ykw%TE-Wv6xh`g1Pmxy9nxe7w ze(PI{6^cd0H#WFzsN0CzDA+i-Y3`<~O&?2mB^OJrODjs>Z{}{k_?699m0x|@lC)*8 z%%N=0R?Jr6*6Z8cw;d=~F3&F?+a9vLa|dHb$&Qyhm+ZVyVOLSNi?B>BD~Ee(8aT1AWbo&CM;EEoH56tE6@EV8X%6-*|u1-NtOIZ>P7H z9s-9XhaP{M`0e$>L5F*fu#U8SXZT%h2eqT56Y5;vIn|ZYCGC#u9zGg)w718lr{jCe z@An_mJyvsE<#^c%!il02pHAkVoIaIx>gnm^(__6$dheWxJ#(!uyl?Pq(Ao3ne9xWf z_v}A;-u3*k3(gmgUSwVDy5w-FbHIL};|Kd6ItCpEJBJ*Hx-UCj?irppeBz4xmD5+f zub#UWaP88_{E^}7QP*$YNVp-r$-DXJR{E{yw{vdK+*xxMeYfPE(!GlNn)e%iH2tw% z>L5Kn>ODH}V8MesW8ASPKV|>)e!S=*`C-L`&P4Mg+egPHeJ3wJUif(YN!F8@r^P=j z|6Kdbc>FRj6+1QlT=e|YubW?}zu5oM?q%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600c-$L_t(&f$i9R$ev{x2Jqjx znNAdQq>`kd8;MFRKPV;fgD5SHQ2!Xx9}Yt#0;vURnrw-f2!5a_6@}>_i2PVl34T_T zSgs5)oth}>KU!G}Os8}2;UCxiY|q|3&%3>QpZDF<+5s2O{an|1ANP4&U*~yUmBjxO zYPaBB9J>YY>ewxKTu@c>a2Ph?703vj9cRIdunK>|l}X+l3GX-xuByH9J)DoHapJBn zcpp5Dqr0kAxFpHntEy%)wZ~QPfp`)JcU8eHxGc##{i1u%RW&ckL|3=zc`NQQ75q8e zi@p1*|Ah;atnRbx7k&zs;2ymGzb1G&uCb+Hcp0Bb@jgTG)op6YC_#xW?ogD>N*BpU|u&!*t2It-uCdjHVQsh9DyBy0NY`lsf1 zaQQZ<*I^Bg$HI;mUc{M6o*U|uCVFJ5tLnq}JkG&qv0#Yl&v7??f{oqA^Fu7d9@=Qu zkataLpXkc3u{6oLq5k!>R@M9@8wUvJ?SlQIu!U_^70$wWI0FYv;pk*MgSGgiHVdYU zbmcwVh!w-8Gp&b~;c(oa}m_gwV zP4s{8Tl@jf;w5|phv4HlvipBT_wKvcbCw*RE`kmC3ho>hl4ydLYg1t|-q3c*g#*Z^ zT3b5{8*yuruTN!E+S>Vztz+I~Y)k0dS_kd5{XUKay$!dtP<48e*M=Dv_QgZmI^0n_ zfeY~iEmX`k`Um5tB;OcjSY26xm8LgUC$tg0U(0cytg1h1GiGPvJ)D%}@j;E1L{%-u zPjTFKl5W5U@F>2SdF~t`onH&I(fuw~Ci(Xu<9@+~+i;Q1B6TFedYjk$6Sy(SkGCSM zx(#0)k(eIR_uI>_pVtzWH?`R|f#2cwBO!v+C*gwe|+aeoyc&Mt2v~|#n!G*W9k$nUYZ!7<9>I;#6DX7PAfRaa@@ZYKB@ zzBpB?I9<%9;O}c2;7qV8$+A)S)5B~EK23}52hM=zt|UuG<59zG-*_y>r?q3`F<7dF zkja?9KeZ!gKfadamXZ22mv>rIY-Fcu7w*sDLw)sECHeM9eVFS@ysCO0AMO5bz}ZRe z>)QTo%k*}2l5SOqpc5t~O$*Uvd9!J5miT42qq3ys%A_P)N2Pz;H1S^QCAliZHBpsxLXay!6qyw-5?Eq4Nbg zTLQF1L?YcxRSVU5fDdqbu}e zk?KwQgXfNL4gANdO!_C2w$arCr_!z;USsyMzB_=)iv20G!5=1L-6X0Q!@%L}QHQd; zx%0rNxK6#ra3(8qII~5yBRu-SD~2~oVmL1~bwquWXRyV*n$4OKUBe!ARLh9^J8cV_ zlu@lB`U1N!>8T^S$4}N{4c_^aP)*KY*CZ*^NjCiq_F2&A6YLYysO4s_c%ac3_K54~&LccEgfL+QK51Sv1 zvf@i=)UQiY*n<_oa#U(A?q+c7c}q;H^?f~s`lzm8hgGu(G0p;n|6-0|r_~&8<$2)Y zSN7z?J(O8q^ZB^$^e^HndYRmgla;)4%-S#HHq5d#zLfspxx1Ub#YH!f?nuOq-Tff0 z@4id>$2ZG11_NAyzaYih0Glty;R7*>Qy_C*<`cW)Vdq@F0o@9yaCqH&!vFvP07*qo IM6N<$g4*~61ONa4 literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/Contents.json new file mode 100644 index 0000000..aad174b --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "arrow-left.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/arrow-left.png b/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/arrow-left.png new file mode 100644 index 0000000000000000000000000000000000000000..8a82ffc2390bdb2737dd3fc35e089d5bbdd449f9 GIT binary patch literal 402 zcmV;D0d4+?P)V3*SD_gu5H_vNs=_=h%@Z~htD{CE^XiU<#H!SoXC=4c!ApuImAj}B770YaY+s_ z{sv~k=j0e80hI8o|D*%( zJnt1n(d4@)1*)nF_@SDx2&N>gYoVi=okBbcIgdg%xb-_zsAnv}?K}*_f`C~3jiO7e zTF8(kR+kc}5}S%SM2XGiG@69bh6YK(cuR>QVRbHqAYpy5HJ0GjI(2z6VOjeZgTh*S&a((~f8T9L;-GvE{J7kU*${gRQJVEKOLC9kZIcJXkUF-5y z4z!6lR><+$#6>=HVanjP+5c>AOUo*U+uOqV>iV)dIj`CZy!^fIaqS1rbD#UZADJm+ zAjl9Tl*Z)XbSQ-3iPsG72ANJJ7Kc?XhD-{si!>NFgeaZalX2eJm95~#-S69@vf8AD-8nfEIiTudgq4)8jVXIIvO%*K6Dgh zTKTYXr-NTbg4P6Sxfz@uE$nJcK@S^uHKbH5&^oZ(dREl*9p`xYL$Ve5;*aihso0?E q8o^Mzu)LYuR;dW&&Ge^x7~b8ur7(A?b|*0W7(8A5T-G@yGywn}#g_U2 literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Contents.json new file mode 100644 index 0000000..0b17967 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Ellipse 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Ellipse 1.png b/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Ellipse 1.png new file mode 100644 index 0000000000000000000000000000000000000000..f0350280d9a6a51f1d3b6ba468968a8b81b776b9 GIT binary patch literal 570 zcmV-A0>%A_P)N2Pz;H1S^QCAliZHBpsxLXay!6qyw-5?Eq4Nbg zTLQF1L?YcxRSVU5fDdqbu}e zk?KwQgXfNL4gANdO!_C2w$arCr_!z;USsyMzB_=)iv20G!5=1L-6X0Q!@%L}QHQd; zx%0rNxK6#ra3(8qII~5yBRu-SD~2~oVmL1~bwquWXRyV*n$4OKUBe!ARLh9^J8cV_ zlu@lB`U1N!>8T^S$4}N{4c_^aP)*KY*CZ*^NjCiq_F2&A6YLYysO4s_c%ac3_K54~&LccEgfL+QK51Sv1 zvf@i=)UQiY*n<_oa#U(A?q+c7c}q;H^?f~s`lzm8hgGu(G0p;n|6-0|r_~&8<$2)Y zSN7z?J(O8q^ZB^$^e^HndYRmgla;)4%-S#HHq5d#zLfspxx1Ub#YH!f?nuOq-Tff0 z@4id>$2ZG11_NAyzaYih0Glty;R7*>Qy_C*<`cW)Vdq@F0o@9yaCqH&!vFvP07*qo IM6N<$g4*~61ONa4 literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/Contents.json new file mode 100644 index 0000000..c2f10ea --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "rotate-right.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/rotate-right.png b/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/rotate-right.png new file mode 100644 index 0000000000000000000000000000000000000000..662594e860f6f4f8086797f7a5dac1cba4a4139c GIT binary patch literal 639 zcmV-_0)YLAP)`z-sxzmdbaqW0~xUNJu27Y=?jKam;Atj zzTjIDv!E}uWIR<_`ra-{Ojqm*znt0)9T9Fx%oSnYx$CTx>*NQAp&hfO|I)X0^7+$a zzBp#hfk(KGy^?9jOSq)Y%VQYzoHcCgoc|TOtRf<%KCtw+ zT;~07_LszzjCUvBv!*YX6+^w18~laJ?ns9xIH$+zz#Dem_p|Nwnb*4_->$PE!M~ zARK5F@Qr;{=^Np(gJE(agfo|a>dYDSf)hCu}K zH7Mamiv09Y=*}-|pC)a{J`}8dFbqK7(`J%z=e_7F&>e-UE&q&QPlBoenU*cg&Jq++ z3bkZEO3{0TM{FGsTHe@uG9rT=68Y?xZF1}YPYf;f_@7w@d*e;|GkBzn16#Pm`;6fc zTL(B@!q5Bk?m$pP2l^&D&^NXY+CNLX7S?Cws$%?)T-7#Lc zcm()TXu2jU5Kd4ktga-qvN-J(|TlRi&sV_zU}zBKO;9&~z@_BBr2-bSeh1T4xb zM2c!vE);lmuC=fwQ7z+9M}hvJRluuq7X>#{aW}zbCAh5ZP`$|8eYOGGtaRd#@uKz} z9m5GMAf;nqlE4vxd{2b%fI~JJY5Rz&4Cf;sG5IPBk$axyI+b;e}Gqh5RdlFEd z6&MaQ3;4orRQkg3*um4eW2PWjyRC&v3v#OEUdv;R-lh=Mpd*U*lhqwNH?t^Qhk%)@ z5^*eGb{XZl_QTr$oiTE5YB}I?1k9q7i07@a6`pI#xyK)4v`>bz1G$zhsyl^7o~DE> zzLPDD-U|X~I{=~Om3=2Ca)cpadf&Dwu*R7%Lc8#XUXF0*efrZ7qb>v3A|7t@5Mt1F z0GvxU0&dfL05>58&^IZ7zG*vv=v~Ai+NR3@o)8bW2}sPpkNLs8BBs#SDK+iI-RywsL!7!j?EbYr$h4&!-IAu>tAJu>_e1#Kp>#3LM%|O z$_)ixovSTuNtDZYWGK)dGz)lD?yTVEEAD1EuLRqg4b_XTsaS+Si~P-l6;o5GF_B0l2EZ>*&l1;1dIJ~$0000 Void)? - var lastAddedButton: NSView? - var loginInfo: NSView? - - let tableView: NSTableView = { - let tableView = NSTableView() - tableView.autoresizingMask = [.width, .height] - tableView.headerView = nil - - let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("column1")) - column.title = "" - column.width = tableView.frame.size.width - column.resizingMask = .autoresizingMask - - tableView.addTableColumn(column) - - return tableView - }() - - let scrollView: NSScrollView = { - let scrollView = NSScrollView() - scrollView.borderType = .bezelBorder - return scrollView - }() - - private var isDeleteButtonsVisible: Bool = false - let toggleDeleteButton: NSButton = { - let button = NSButton(title: "-", target: nil, action: nil) - button.bezelStyle = .rounded - return button - }() - - @objc func toggleDeleteButtons() { - print("toggleDeleteButtons") - isDeleteButtonsVisible.toggle() - - let numberOfRows = tableView.numberOfRows - for row in 0.. Void) { - print("init") - self.clickAction = clickAction - super.init(frame: BoxSizeManager.shared.buttonGroupSizeNSRect) - // setupButtons() - - for item in boxVM.webViewURL.URLstring { - buttonArray.append(item.name) - } - - scrollView.documentView = tableView - super.addSubview(scrollView) - scrollView.snp.makeConstraints { make in - make.edges.equalToSuperview() - } - - tableView.dataSource = self - tableView.delegate = self - tableView.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) - - super.addSubview(toggleDeleteButton) - toggleDeleteButton.target = self - toggleDeleteButton.action = #selector(toggleDeleteButtons) - toggleDeleteButton.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.bottom.equalToSuperview().offset(0) - } - - super.addSubview(addButton) - addButton.target = self - addButton.action = #selector(addCell) - addButton.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.bottom.equalTo(toggleDeleteButton.snp.top).offset(-10) - - } - } - - @objc func addCell() { - buttonArray.append("New Cell") // 'New Cell'은 신규 셀의 이름입니다. 필요에 따라 변경하십시오. - tableView.reloadData() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ dirtyRect: NSRect) { - // 뷰의 커스텀 렌더링에 사용됨. - } - - private func setupButtons() { - for subview in self.subviews { - subview.removeFromSuperview() - } - - for (name, _) in boxVM.webViewURL.URLstring { - self.createButton(name) - } - } - - @objc private func clickBtn(sender: NSButton) { - clickAction?(sender) - } - - private func createButton(_ title: String) { - let button: NSButton - - if title == "home" { - button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) - button.imagePosition = .imageOnly - button.isBordered = false - } else { - button = HoverButton() - button.title = title - - button.wantsLayer = true - button.contentTintColor = NSColor.black - button.layer?.borderColor = NSColor.black.cgColor - button.layer?.borderWidth = 1.0 - button.layer?.cornerRadius = 5.0 - button.layer?.opacity = 0.7 - } - super.addSubview(button) - - button.target = self - button.action = #selector(clickBtn(sender:)) - - let fontSize: CGFloat = 16.0 - button.font = NSFont.systemFont(ofSize: fontSize) - button.setButtonType(.momentaryLight) - button.translatesAutoresizingMaskIntoConstraints = false - - button.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.leading.equalToSuperview().offset(10) - make.trailing.equalToSuperview().offset(-10) - - if title == "home" { - make.height.equalTo(50) - } else { - make.height.equalTo(50) - } - - if let lastButton = lastAddedButton { - make.top.equalTo(lastButton.snp.bottom).offset(10) - } else { - make.top.equalToSuperview().offset(10) - } - } - lastAddedButton = button - } -} - -//NSTableViewDelegate -extension BoxButtonViewGroup: NSTableViewDataSource, NSTableViewDelegate { - func numberOfRows(in tableView: NSTableView) -> Int { - return buttonArray.count - } - - func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { - let cellView = CustomTableCellView() - cellView.layer?.backgroundColor = NSColor.red.cgColor - cellView.rowIndex = row - - let button = NSButton(title: buttonArray[row], target: self, action: #selector(buttonClicked(_:))) - button.tag = row - cellView.addSubview(button) - - let fontSize: CGFloat = 16.0 - button.font = NSFont.systemFont(ofSize: fontSize) - button.setButtonType(.momentaryLight) - button.bezelStyle = .shadowlessSquare - - button.wantsLayer = true - button.layer?.borderWidth = 0 - button.layer?.cornerRadius = 10 - button.layer?.backgroundColor = NSColor.orange.cgColor - - button.snp.makeConstraints { make in - make.width.equalTo(100) - make.height.equalTo(50) - make.top.bottom.equalToSuperview().inset(5) - } - - let deleteButton = NSButton(title: "삭제", target: self, action: #selector(deleteButtonClicked(_:))) - deleteButton.tag = row - deleteButton.bezelStyle = .shadowlessSquare - deleteButton.wantsLayer = true - deleteButton.layer?.borderWidth = 0 - deleteButton.layer?.cornerRadius = 10 - deleteButton.layer?.backgroundColor = NSColor.red.cgColor - - cellView.addSubview(deleteButton) - deleteButton.snp.makeConstraints { make in - make.trailing.equalToSuperview().offset(-5) - make.top.bottom.equalToSuperview().inset(5) - } - cellView.deleteButton = deleteButton - cellView.deleteButton.isHidden = !isDeleteButtonsVisible - - return cellView - } - - - @objc func deleteButtonClicked(_ sender: NSButton) { - let row = sender.tag - print("Delete button clicked in row: \(row)") - - // 데이터 목록에서 항목 제거 - buttonArray.remove(at: row) - tableView.reloadData() - // 테이블 뷰에서 행 제거 및 셀 인덱스 업데이트 - tableView.removeRows(at: IndexSet(integer: row), withAnimation: .effectFade) - for (_, subview) in tableView.subviews.enumerated() { - guard let cellView = subview as? CustomTableCellView else { - continue - } - - cellView.rowIndex = tableView.row(for: cellView) - cellView.button.tag = cellView.rowIndex - cellView.deleteButton.tag = cellView.rowIndex - - cellView.button.title = buttonArray[cellView.rowIndex] - } - } - - - func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { - return 40.0 - } - - @objc func buttonClicked(_ sender: NSButton) { - let row = sender.tag - print("Button clicked in row: \(row)") - } - - // Drag and Drop methods - func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? { - let pasteboardItem = NSPasteboardItem() - pasteboardItem.setString(String(row), forType: .string) - return pasteboardItem - } - - func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { - if dropOperation == .above { - return .move - } else { - return [] - } - } - - func tableView(_ aTableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool { - guard let str = info.draggingPasteboard.string(forType: .string), let from = Int(str) else { - return false - } - - let to = (from < row) ? row - 1 : row - let item = buttonArray[from] - buttonArray.remove(at: from) - buttonArray.insert(item, at: to) - tableView.reloadData() - - for (_, subview) in tableView.subviews.enumerated() { - guard let cellView = subview as? CustomTableCellView else { - continue - } - - cellView.button.title = buttonArray[cellView.rowIndex] - } - - return true - } -} diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift deleted file mode 100644 index 38165ca..0000000 --- a/Box42/Window/BoxWindowController.swift +++ /dev/null @@ -1,136 +0,0 @@ -// -// BoxWindowController.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa - -class BoxWindowController: NSWindowController, NSToolbarDelegate, NSWindowDelegate { - override init(window: NSWindow?) { - let contentRect = BoxSizeManager.shared.boxViewSizeNSRect - let styleMask: NSWindow.StyleMask = [.resizable, .closable, .miniaturizable, .fullSizeContentView] - let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) - - windowInstance.titlebarAppearsTransparent = true - windowInstance.titleVisibility = .hidden - windowInstance.title = "Box" - windowInstance.isReleasedWhenClosed = false - windowInstance.isOpaque = false - windowInstance.backgroundColor = .clear - windowInstance.isMovableByWindowBackground = true - - let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) - windowInstance.contentViewController = boxViewController - - super.init(window: windowInstance) - - windowInstance.delegate = self - - setupToolbar() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -extension BoxWindowController { - func windowShouldClose(_ sender: NSWindow) -> Bool { -// NSApplication.shared.terminate(self) - StateManager.shared.toggleShowWindow() - return true - } -} - -// MARK: - Toolbar -extension BoxWindowController { - func setupToolbar() { - let toolbar = NSToolbar(identifier: "MainToolbar") - toolbar.delegate = self - toolbar.displayMode = .iconOnly - toolbar.sizeMode = .small - self.window?.toolbar = toolbar - } - - func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - return [.group] - } - - func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - return [.group, .flexibleSpace, .sidebar, .flexibleSpace, .goBack, .flexibleSpace, .goFoward, .flexibleSpace, .reloadPage, .flexibleSpace, .goToHome] - } - - func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { - switch itemIdentifier { - case .group: - let groupItem = NSToolbarItemGroup(itemIdentifier: .group) - - let sidebarItem = NSToolbarItem(itemIdentifier: .sidebar) - sidebarItem.label = "Sidebar" - sidebarItem.image = NSImage(named: NSImage.Name("sidebar.leading")) - sidebarItem.action = #selector(toggleSidebar) - sidebarItem.minSize = NSSize(width: 40, height: 40) - sidebarItem.maxSize = NSSize(width: 40, height: 40) - - let goBack = NSToolbarItem(itemIdentifier: .goBack) - goBack.label = "left" - goBack.image = NSImage(named: NSImage.Name("arrow.left")) // 이미지 설정 - goBack.action = #selector(goBackAction) // 해당 action 설정 - - let goFoward = NSToolbarItem(itemIdentifier: .goFoward) - goFoward.label = "right" - goFoward.image = NSImage(named: NSImage.Name("arrow.right")) - goFoward.action = #selector(goFowardAction) - - let reloadPage = NSToolbarItem(itemIdentifier: .reloadPage) - reloadPage.label = "clockwise" - reloadPage.image = NSImage(named: NSImage.Name("arrow.clockwise")) - reloadPage.action = #selector(reloadPageAction) - - let goToHome = NSToolbarItem(itemIdentifier: .goToHome) - goToHome.label = "skating" - goToHome.image = NSImage(named: NSImage.Name("figure.skating")) - goToHome.action = #selector(goToHomeAction) - - groupItem.subitems = [sidebarItem, goBack, goFoward, reloadPage, goToHome] - - return groupItem - - default: - return nil - } - } - - @objc func toggleSidebar() { - print("sidebar") - } - - @objc func goBackAction() { - WebViewManager.shared.hostingWebView?.goBack() - } - - @objc func goFowardAction() { - WebViewManager.shared.hostingWebView?.goForward() - } - - @objc func reloadPageAction() { - WebViewManager.shared.hostingWebView?.reload() - } - - @objc func goToHomeAction() { - if let item = WebViewManager.shared.hostingWebView?.backForwardList.backList.first { - WebViewManager.shared.hostingWebView?.go(to: item) - } - } -} - -extension NSToolbarItem.Identifier { - static let sidebar = NSToolbarItem.Identifier(rawValue: "SidebarButton") - static let goBack = NSToolbarItem.Identifier(rawValue: "goBackButton") - static let goFoward = NSToolbarItem.Identifier(rawValue: "goFowardButton") - static let reloadPage = NSToolbarItem.Identifier(rawValue: "reloadPageButton") - static let goToHome = NSToolbarItem.Identifier(rawValue: "goToHomeButton") - static let group = NSToolbarItem.Identifier(rawValue: "ItemGroup") -} diff --git a/Box42/Window/View/WindowCloseButton.swift b/Box42/Window/View/WindowCloseButton.swift deleted file mode 100644 index 0e9a747..0000000 --- a/Box42/Window/View/WindowCloseButton.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// WindowCloseButton.swift -// Box42 -// -// Created by Chanhee Kim on 8/23/23. -// - -import AppKit - -class WindowCloseButton: NSButton { - - private var callback: (() -> Void)? - - init(image: NSImage, completion: @escaping () -> Void) { - super.init(frame: .zero) - - self.title = "X" // 기본적인 X 모양으로 표시. 이미지나 다른 디자인을 원하시면 변경하실 수 있습니다. - self.bezelStyle = .texturedRounded - self.target = self - self.action = #selector(closeAction) - self.callback = completion - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func closeAction() { - callback?() - } -} diff --git a/Box42/Window/View/WindowMaximizeButton.swift b/Box42/Window/View/WindowMaximizeButton.swift deleted file mode 100644 index dde3691..0000000 --- a/Box42/Window/View/WindowMaximizeButton.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// WindowMaximizeButton.swift -// Box42 -// -// Created by Chanhee Kim on 8/23/23. -// - -import AppKit - -class WindowMaximizeButton: NSButton { - - private var callback: (() -> Void)? - - init(image: NSImage, completion: @escaping () -> Void) { - super.init(frame: .zero) - - self.title = "□" // 기본적인 □ 모양으로 표시. 변경 가능. - self.bezelStyle = .texturedRounded - self.target = self - self.action = #selector(maximizeAction) - self.callback = completion - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func maximizeAction() { - callback?() - } -} diff --git a/Box42/Window/View/WindowMinimizeButton.swift b/Box42/Window/View/WindowMinimizeButton.swift deleted file mode 100644 index e940fb5..0000000 --- a/Box42/Window/View/WindowMinimizeButton.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// WindowMinimizeButton.swift -// Box42 -// -// Created by Chanhee Kim on 8/23/23. -// - -import AppKit - -class WindowMinimizeButton: NSButton { - - private var callback: (() -> Void)? - - init(image: NSImage, completion: @escaping () -> Void) { - super.init(frame: .zero) - - self.title = "_" // 기본적인 _ 모양으로 표시. 변경 가능. - self.bezelStyle = .texturedRounded - self.target = self - self.action = #selector(minimizeAction) - self.callback = completion - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func minimizeAction() { - callback?() - } -} diff --git a/Box42/Window/View/WindowViewGroup.swift b/Box42/Window/View/WindowViewGroup.swift deleted file mode 100644 index f96abec..0000000 --- a/Box42/Window/View/WindowViewGroup.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// WindowViewGroup.swift -// Box42 -// -// Created by Chanhee Kim on 8/23/23. -// - -import AppKit -import SnapKit - -class WindowViewGroup: NSView { - lazy var windowClose: WindowCloseButton = WindowCloseButton(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.close?() }) - lazy var windowMinimize: WindowMinimizeButton = WindowMinimizeButton(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.minimize?()} ) - lazy var windowMaximize: WindowMaximizeButton = WindowMaximizeButton(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.maximize?() }) - - var close: (() -> Void)? - var minimize: (() -> Void)? - var maximize: (() -> Void)? - - override init(frame: NSRect) { - super.init(frame: frame) - setupViews() - setupConstraints() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setupViews() - setupConstraints() - } - - private func setupViews() { - self.addSubview(windowClose) - self.addSubview(windowMinimize) - self.addSubview(windowMaximize) - } - - private func setupConstraints() { - - windowClose.snp.makeConstraints { make in - make.top.left.bottom.equalToSuperview() - make.width.equalTo(windowMinimize) - } - - windowMinimize.snp.makeConstraints { make in - make.top.bottom.equalTo(windowClose) - make.left.equalTo(windowClose.snp.right).offset(10) - make.width.equalTo(windowMaximize) - } - - windowMaximize.snp.makeConstraints { make in - make.top.right.bottom.equalToSuperview() - make.left.equalTo(windowMinimize.snp.right).offset(10) - } - } -} diff --git a/Box42/Window/WindowButtonViewController.swift b/Box42/Window/WindowButtonViewController.swift deleted file mode 100644 index 511ef8c..0000000 --- a/Box42/Window/WindowButtonViewController.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// WindowButtonViewController.swift -// Box42 -// -// Created by Chanhee Kim on 8/23/23. -// - -import Cocoa - -class WindowButtonViewController: NSViewController { - override func loadView() { - let windowViewGroup = WindowViewGroup() - - windowViewGroup.close = windowClose - windowViewGroup.minimize = windowMin - windowViewGroup.maximize = windowMax - - self.view = windowViewGroup - } - - override func viewDidLoad() { - super.viewDidLoad() - } - - func windowClose() { - print("close") - } - - func windowMin() { - print("min") - } - - func windowMax() { - print("max") - } -} From ae3d2099e97a11bf2f556c23430a3a217e54c228 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:14:31 +0900 Subject: [PATCH 12/33] =?UTF-8?q?chore:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 30 ++++++++++++++---- .../Assets.xcassets/uibuttons/Ellipse 1.png | Bin 570 -> 0 bytes 2 files changed, 23 insertions(+), 7 deletions(-) delete mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Ellipse 1.png diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 0d9fb62..337d15f 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ DE3FF3752A978AB8009C88EF /* WindowViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */; }; DE3FF3762A978AB8009C88EF /* WindowCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */; }; DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */; }; + DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3FF3A22A97D2A6009C88EF /* DisplayURLTextfield.swift */; }; DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4407F92A923E860091937A /* BoxFunctionViewController.swift */; }; DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */; }; DE4408022A923EB60091937A /* PinButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408012A923EB60091937A /* PinButtonView.swift */; }; @@ -67,6 +68,7 @@ DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F532A591F1400FC3B77 /* PreferencesView.swift */; }; DE874F572A591F2500FC3B77 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F562A591F2500FC3B77 /* Icon.swift */; }; DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* String.swift */; }; + DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */; }; DEB862D42A85124500278FCD /* cleanCache.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D32A85124500278FCD /* cleanCache.sh */; }; DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862DC2A85347400278FCD /* Scripts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862DB2A85347400278FCD /* Scripts.swift */; }; @@ -122,6 +124,7 @@ DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowViewGroup.swift; sourceTree = ""; }; DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowCloseButton.swift; sourceTree = ""; }; DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowMinimizeButton.swift; sourceTree = ""; }; + DE3FF3A22A97D2A6009C88EF /* DisplayURLTextfield.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayURLTextfield.swift; sourceTree = ""; }; DE4407F92A923E860091937A /* BoxFunctionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionViewController.swift; sourceTree = ""; }; DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceButtonView.swift; sourceTree = ""; }; DE4408012A923EB60091937A /* PinButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinButtonView.swift; sourceTree = ""; }; @@ -137,6 +140,7 @@ DE874F532A591F1400FC3B77 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; DE874F562A591F2500FC3B77 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; DE874F5E2A5935CC00FC3B77 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; + DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupViewController.swift; sourceTree = ""; }; DEB862D32A85124500278FCD /* cleanCache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cleanCache.sh; sourceTree = ""; }; DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862DB2A85347400278FCD /* Scripts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Scripts.swift; path = Box42/Scripts/Scripts.swift; sourceTree = SOURCE_ROOT; }; @@ -179,16 +183,17 @@ children = ( DE77BA542A82636500713683 /* Shared */, DEF749302A85655E00D987C8 /* Extensions */, + DE018C0E2A509C0C00FF0AA3 /* Menubar */, + DE9DA8122A97F1E2001C0D3B /* ButtonGroup */, DE1F1A202A8B50CA00A88DD8 /* Main */, - DEB862E82A853F6800278FCD /* Window */, DEB862D22A8511D600278FCD /* Scripts */, DE874F512A591EC600FC3B77 /* Preferences */, DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, + DEB862E82A853F6800278FCD /* WindowButton */, DE0A917D2A8F864300D1D6F1 /* Toolbar */, DE4407F82A923E5B0091937A /* FunctionButton */, - DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; sourceTree = ""; @@ -271,6 +276,7 @@ children = ( DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */, DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */, + DE3FF3A22A97D2A6009C88EF /* DisplayURLTextfield.swift */, DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */, DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */, DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */, @@ -294,6 +300,7 @@ DE4408202A9297EE0091937A /* View */, DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */, + DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, ); name = Main; sourceTree = ""; @@ -302,8 +309,8 @@ isa = PBXGroup; children = ( DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */, - DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */, DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */, + DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */, DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */, ); path = View; @@ -334,7 +341,6 @@ DE4408202A9297EE0091937A /* View */ = { isa = PBXGroup; children = ( - DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); @@ -363,6 +369,15 @@ path = Preferences; sourceTree = ""; }; + DE9DA8122A97F1E2001C0D3B /* ButtonGroup */ = { + isa = PBXGroup; + children = ( + DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, + DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */, + ); + path = ButtonGroup; + sourceTree = ""; + }; DEB862D22A8511D600278FCD /* Scripts */ = { isa = PBXGroup; children = ( @@ -385,14 +400,13 @@ path = sh; sourceTree = ""; }; - DEB862E82A853F6800278FCD /* Window */ = { + DEB862E82A853F6800278FCD /* WindowButton */ = { isa = PBXGroup; children = ( DE3FF36F2A978A6E009C88EF /* View */, DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */, - DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, ); - path = Window; + path = WindowButton; sourceTree = ""; }; DEF749302A85655E00D987C8 /* Extensions */ = { @@ -493,8 +507,10 @@ DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, + DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */, DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, DE3FF3742A978AB8009C88EF /* WindowMaximizeButton.swift in Sources */, + DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Ellipse 1.png b/Box42/Resources/Assets.xcassets/uibuttons/Ellipse 1.png deleted file mode 100644 index f0350280d9a6a51f1d3b6ba468968a8b81b776b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 570 zcmV-A0>%A_P)N2Pz;H1S^QCAliZHBpsxLXay!6qyw-5?Eq4Nbg zTLQF1L?YcxRSVU5fDdqbu}e zk?KwQgXfNL4gANdO!_C2w$arCr_!z;USsyMzB_=)iv20G!5=1L-6X0Q!@%L}QHQd; zx%0rNxK6#ra3(8qII~5yBRu-SD~2~oVmL1~bwquWXRyV*n$4OKUBe!ARLh9^J8cV_ zlu@lB`U1N!>8T^S$4}N{4c_^aP)*KY*CZ*^NjCiq_F2&A6YLYysO4s_c%ac3_K54~&LccEgfL+QK51Sv1 zvf@i=)UQiY*n<_oa#U(A?q+c7c}q;H^?f~s`lzm8hgGu(G0p;n|6-0|r_~&8<$2)Y zSN7z?J(O8q^ZB^$^e^HndYRmgla;)4%-S#HHq5d#zLfspxx1Ub#YH!f?nuOq-Tff0 z@4id>$2ZG11_NAyzaYih0Glty;R7*>Qy_C*<`cW)Vdq@F0o@9yaCqH&!vFvP07*qo IM6N<$g4*~61ONa4 From 74378482c249ae19e8610ec8176b8b1934c292c8 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:15:09 +0900 Subject: [PATCH 13/33] =?UTF-8?q?fix:=20window=20controller=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=91=EC=86=8D=EC=8B=9C=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=82=AC=EC=9A=A9=EB=AA=BB=ED=95=98?= =?UTF-8?q?=EB=8D=98=20=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/BoxWindowController.swift | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Box42/BoxWindowController.swift diff --git a/Box42/BoxWindowController.swift b/Box42/BoxWindowController.swift new file mode 100644 index 0000000..3a3babf --- /dev/null +++ b/Box42/BoxWindowController.swift @@ -0,0 +1,41 @@ +// +// BoxWindowController.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxWindowController: NSWindowController, NSWindowDelegate { + override init(window: NSWindow?) { + let contentRect = BoxSizeManager.shared.boxViewSizeNSRect + let styleMask: NSWindow.StyleMask = [.resizable, .titled, .fullSizeContentView, .closable, .miniaturizable] + let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) + super.init(window: windowInstance) + windowInstance.delegate = self + + windowInstance.title = "Box" + windowInstance.titlebarAppearsTransparent = true + windowInstance.titleVisibility = .hidden + windowInstance.isReleasedWhenClosed = false + windowInstance.isMovableByWindowBackground = true + + let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) + windowInstance.contentViewController = boxViewController + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension BoxWindowController { + func windowWillClose(_ notification: Notification) { + StateManager.shared.showWindow = false + } + + func windowWillMiniaturize(_ notification: Notification) { + StateManager.shared.showWindow = false + } +} From dce80e9847e335b87aa6ae07ce240f7d243ece27 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:16:52 +0900 Subject: [PATCH 14/33] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=A1=B0=EB=A5=BC?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/ButtonGroup/BoxButtonViewGroup.swift | 309 ++++++++++++++++++ .../ButtonGroupViewController.swift | 35 ++ 2 files changed, 344 insertions(+) create mode 100644 Box42/ButtonGroup/BoxButtonViewGroup.swift create mode 100644 Box42/ButtonGroup/ButtonGroupViewController.swift diff --git a/Box42/ButtonGroup/BoxButtonViewGroup.swift b/Box42/ButtonGroup/BoxButtonViewGroup.swift new file mode 100644 index 0000000..512d3c0 --- /dev/null +++ b/Box42/ButtonGroup/BoxButtonViewGroup.swift @@ -0,0 +1,309 @@ +// +// BoxButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa +import SnapKit + +class CustomTableCellView: NSTableCellView { + var button: NSButton! + var deleteButton: NSButton! + var rowIndex: Int! +} + +class BoxButtonViewGroup: NSView { + var boxVM: WebViewModel = WebViewModel() + var pinSwitch : NSSwitch = NSSwitch() + var clickAction: ((NSButton) -> Void)? + var lastAddedButton: NSView? + var loginInfo: NSView? + + let tableView: NSTableView = { + let tableView = NSTableView() + tableView.autoresizingMask = [.width, .height] + tableView.headerView = nil + + let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("column1")) + column.title = "" + column.width = tableView.frame.size.width + column.resizingMask = .autoresizingMask + + tableView.addTableColumn(column) + + return tableView + }() + + let scrollView: NSScrollView = { + let scrollView = NSScrollView() + scrollView.borderType = .bezelBorder + return scrollView + }() + + private var isDeleteButtonsVisible: Bool = false + let toggleDeleteButton: NSButton = { + let button = NSButton(title: "-", target: nil, action: nil) + button.bezelStyle = .rounded + return button + }() + + @objc func toggleDeleteButtons() { + print("toggleDeleteButtons") + isDeleteButtonsVisible.toggle() + + let numberOfRows = tableView.numberOfRows + for row in 0.. Void) { + print("init") + self.clickAction = clickAction + super.init(frame: BoxSizeManager.shared.buttonGroupSizeNSRect) + // setupButtons() + + for item in boxVM.webViewURL.URLstring { + buttonArray.append(item.name) + } + + scrollView.documentView = tableView + super.addSubview(scrollView) + scrollView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + tableView.dataSource = self + tableView.delegate = self + tableView.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) + + super.addSubview(toggleDeleteButton) + toggleDeleteButton.target = self + toggleDeleteButton.action = #selector(toggleDeleteButtons) + toggleDeleteButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(0) + } + + super.addSubview(addButton) + addButton.target = self + addButton.action = #selector(addCell) + addButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalTo(toggleDeleteButton.snp.top).offset(-10) + + } + } + + @objc func addCell() { + buttonArray.append("New Cell") // 'New Cell'은 신규 셀의 이름입니다. 필요에 따라 변경하십시오. + tableView.reloadData() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ dirtyRect: NSRect) { + // 뷰의 커스텀 렌더링에 사용됨. + } + + private func setupButtons() { + for subview in self.subviews { + subview.removeFromSuperview() + } + + for (name, _) in boxVM.webViewURL.URLstring { + self.createButton(name) + } + } + + @objc private func clickBtn(sender: NSButton) { + clickAction?(sender) + } + + private func createButton(_ title: String) { + let button: NSButton + + if title == "home" { + button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) + button.imagePosition = .imageOnly + button.isBordered = false + } else { + button = HoverButton() + button.title = title + + button.wantsLayer = true + button.contentTintColor = NSColor.black + button.layer?.borderColor = NSColor.black.cgColor + button.layer?.borderWidth = 1.0 + button.layer?.cornerRadius = 5.0 + button.layer?.opacity = 0.7 + } + super.addSubview(button) + + button.target = self + button.action = #selector(clickBtn(sender:)) + + let fontSize: CGFloat = 16.0 + button.font = NSFont.systemFont(ofSize: fontSize) + button.setButtonType(.momentaryLight) + button.translatesAutoresizingMaskIntoConstraints = false + + button.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.leading.equalToSuperview().offset(10) + make.trailing.equalToSuperview().offset(-10) + + if title == "home" { + make.height.equalTo(50) + } else { + make.height.equalTo(50) + } + + if let lastButton = lastAddedButton { + make.top.equalTo(lastButton.snp.bottom).offset(10) + } else { + make.top.equalToSuperview().offset(10) + } + } + lastAddedButton = button + } +} + +//NSTableViewDelegate +extension BoxButtonViewGroup: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + return buttonArray.count + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + let cellView = CustomTableCellView() + cellView.layer?.backgroundColor = NSColor.red.cgColor + cellView.rowIndex = row + + let button = NSButton(title: buttonArray[row], target: self, action: #selector(buttonClicked(_:))) + button.tag = row + cellView.addSubview(button) + + let fontSize: CGFloat = 16.0 + button.font = NSFont.systemFont(ofSize: fontSize) + button.setButtonType(.momentaryLight) + button.bezelStyle = .shadowlessSquare + + button.wantsLayer = true + button.layer?.borderWidth = 0 + button.layer?.cornerRadius = 10 + button.layer?.backgroundColor = NSColor.orange.cgColor + + button.snp.makeConstraints { make in + make.width.equalTo(100) + make.height.equalTo(50) + make.top.bottom.equalToSuperview().inset(5) + } + + let deleteButton = NSButton(title: "삭제", target: self, action: #selector(deleteButtonClicked(_:))) + deleteButton.tag = row + deleteButton.bezelStyle = .shadowlessSquare + deleteButton.wantsLayer = true + deleteButton.layer?.borderWidth = 0 + deleteButton.layer?.cornerRadius = 10 + deleteButton.layer?.backgroundColor = NSColor.red.cgColor + + cellView.addSubview(deleteButton) + deleteButton.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-5) + make.top.bottom.equalToSuperview().inset(5) + } + cellView.deleteButton = deleteButton + cellView.deleteButton.isHidden = !isDeleteButtonsVisible + + return cellView + } + + + @objc func deleteButtonClicked(_ sender: NSButton) { + let row = sender.tag + print("Delete button clicked in row: \(row)") + + // 데이터 목록에서 항목 제거 + buttonArray.remove(at: row) + tableView.reloadData() + // 테이블 뷰에서 행 제거 및 셀 인덱스 업데이트 + tableView.removeRows(at: IndexSet(integer: row), withAnimation: .effectFade) + for (_, subview) in tableView.subviews.enumerated() { + guard let cellView = subview as? CustomTableCellView else { + continue + } + + cellView.rowIndex = tableView.row(for: cellView) + cellView.button.tag = cellView.rowIndex + cellView.deleteButton.tag = cellView.rowIndex + + cellView.button.title = buttonArray[cellView.rowIndex] + } + } + + + func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { + return 40.0 + } + + @objc func buttonClicked(_ sender: NSButton) { + let row = sender.tag + print("Button clicked in row: \(row)") + } + + // Drag and Drop methods + func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? { + let pasteboardItem = NSPasteboardItem() + pasteboardItem.setString(String(row), forType: .string) + return pasteboardItem + } + + func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { + if dropOperation == .above { + return .move + } else { + return [] + } + } + + func tableView(_ aTableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool { + guard let str = info.draggingPasteboard.string(forType: .string), let from = Int(str) else { + return false + } + + let to = (from < row) ? row - 1 : row + let item = buttonArray[from] + buttonArray.remove(at: from) + buttonArray.insert(item, at: to) + tableView.reloadData() + + for (_, subview) in tableView.subviews.enumerated() { + guard let cellView = subview as? CustomTableCellView else { + continue + } + + cellView.button.title = buttonArray[cellView.rowIndex] + } + + return true + } +} diff --git a/Box42/ButtonGroup/ButtonGroupViewController.swift b/Box42/ButtonGroup/ButtonGroupViewController.swift new file mode 100644 index 0000000..2101feb --- /dev/null +++ b/Box42/ButtonGroup/ButtonGroupViewController.swift @@ -0,0 +1,35 @@ +// +// ButtonGroupViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import Cocoa + +class ButtonGroupViewController: NSViewController { + override func loadView() { +// let ButtonViewGroup = BoxButtonViewGroup() + let ButtonViewGroup = NSView() + ButtonViewGroup.wantsLayer = true + ButtonViewGroup.layer?.backgroundColor = NSColor.black.cgColor + self.view = ButtonViewGroup + } + + override func viewDidLoad() { + super.viewDidLoad() + } + + func preference() { + print("preference") + } + + func pin() { + print("pin") + } + + func quit() { + print("quit") + NSApplication.shared.terminate(self) + } +} From cc0612467124c90bc93a976ed66ebcf6b1c7b615 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:17:37 +0900 Subject: [PATCH 15/33] =?UTF-8?q?fix:=20button=20=EB=B0=B0=EA=B2=BD=20?= =?UTF-8?q?=ED=88=AC=EB=AA=85=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/FunctionButton/View/BoxFunctionButtonView.swift | 4 +++- Box42/FunctionButton/View/PinButtonView.swift | 4 +++- Box42/FunctionButton/View/PreferenceButtonView.swift | 4 +++- Box42/FunctionButton/View/QuitButtonView.swift | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Box42/FunctionButton/View/BoxFunctionButtonView.swift b/Box42/FunctionButton/View/BoxFunctionButtonView.swift index 01eb568..b0fd5fc 100644 --- a/Box42/FunctionButton/View/BoxFunctionButtonView.swift +++ b/Box42/FunctionButton/View/BoxFunctionButtonView.swift @@ -15,7 +15,9 @@ class BoxFunctionButtonView: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(BoxFunction) self.callback = completion diff --git a/Box42/FunctionButton/View/PinButtonView.swift b/Box42/FunctionButton/View/PinButtonView.swift index a91036b..f80e9d3 100644 --- a/Box42/FunctionButton/View/PinButtonView.swift +++ b/Box42/FunctionButton/View/PinButtonView.swift @@ -15,7 +15,9 @@ class PinButtonView: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(pin) self.callback = completion diff --git a/Box42/FunctionButton/View/PreferenceButtonView.swift b/Box42/FunctionButton/View/PreferenceButtonView.swift index ffc8102..7c7a324 100644 --- a/Box42/FunctionButton/View/PreferenceButtonView.swift +++ b/Box42/FunctionButton/View/PreferenceButtonView.swift @@ -14,7 +14,9 @@ class PreferenceButtonView: NSButton { init(image: NSImage, completion: @escaping () -> Void) { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(preference) self.callback = completion diff --git a/Box42/FunctionButton/View/QuitButtonView.swift b/Box42/FunctionButton/View/QuitButtonView.swift index aaf9259..eec8ed7 100644 --- a/Box42/FunctionButton/View/QuitButtonView.swift +++ b/Box42/FunctionButton/View/QuitButtonView.swift @@ -15,7 +15,9 @@ class QuitButtonView: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(QuitButton) self.callback = completion From 1eedc044c0434b1ebe13bd4684da28330441022c Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:18:06 +0900 Subject: [PATCH 16/33] =?UTF-8?q?feat:=20=EC=83=81=EB=8B=A8=20window=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=82=AC=EC=9A=A9=20=EC=8B=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=90=A0=20=EA=B2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WindowButton/View/WindowCloseButton.swift | 55 +++++++++++++++++ .../View/WindowMaximizeButton.swift | 55 +++++++++++++++++ .../View/WindowMinimizeButton.swift | 55 +++++++++++++++++ Box42/WindowButton/View/WindowViewGroup.swift | 61 +++++++++++++++++++ .../WindowButtonViewController.swift | 38 ++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 Box42/WindowButton/View/WindowCloseButton.swift create mode 100644 Box42/WindowButton/View/WindowMaximizeButton.swift create mode 100644 Box42/WindowButton/View/WindowMinimizeButton.swift create mode 100644 Box42/WindowButton/View/WindowViewGroup.swift create mode 100644 Box42/WindowButton/WindowButtonViewController.swift diff --git a/Box42/WindowButton/View/WindowCloseButton.swift b/Box42/WindowButton/View/WindowCloseButton.swift new file mode 100644 index 0000000..84074b3 --- /dev/null +++ b/Box42/WindowButton/View/WindowCloseButton.swift @@ -0,0 +1,55 @@ +// +// WindowCloseButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowCloseButton: NSButton { + + private var callback: (() -> Void)? + + init(completion: @escaping () -> Void) { + super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = 21 / 2 + self.layer?.backgroundColor = NSColor.white.cgColor + self.target = self + self.action = #selector(closeAction) + self.callback = completion + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func closeAction() { + callback?() + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.red.cgColor + }, completionHandler: nil) + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.white.cgColor + }, completionHandler: nil) + } +} diff --git a/Box42/WindowButton/View/WindowMaximizeButton.swift b/Box42/WindowButton/View/WindowMaximizeButton.swift new file mode 100644 index 0000000..5934059 --- /dev/null +++ b/Box42/WindowButton/View/WindowMaximizeButton.swift @@ -0,0 +1,55 @@ +// +// WindowMaximizeButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowMaximizeButton: NSButton { + + private var callback: (() -> Void)? + + init(completion: @escaping () -> Void) { + super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = 21 / 2 + self.layer?.backgroundColor = NSColor.white.cgColor + self.target = self + self.action = #selector(maximizeAction) + self.callback = completion + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func maximizeAction() { + callback?() + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.green.cgColor + }, completionHandler: nil) + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.white.cgColor + }, completionHandler: nil) + } +} diff --git a/Box42/WindowButton/View/WindowMinimizeButton.swift b/Box42/WindowButton/View/WindowMinimizeButton.swift new file mode 100644 index 0000000..c628742 --- /dev/null +++ b/Box42/WindowButton/View/WindowMinimizeButton.swift @@ -0,0 +1,55 @@ +// +// WindowMinimizeButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit + +class WindowMinimizeButton: NSButton { + + private var callback: (() -> Void)? + + init(completion: @escaping () -> Void) { + super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = 21 / 2 + self.layer?.backgroundColor = NSColor.white.cgColor + self.target = self + self.action = #selector(minimizeAction) + self.callback = completion + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func minimizeAction() { + callback?() + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.yellow.cgColor + }, completionHandler: nil) + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + NSAnimationContext.runAnimationGroup({ (context) in + context.duration = 2 + self.layer?.backgroundColor = NSColor.white.cgColor + }, completionHandler: nil) + } +} diff --git a/Box42/WindowButton/View/WindowViewGroup.swift b/Box42/WindowButton/View/WindowViewGroup.swift new file mode 100644 index 0000000..9891bcc --- /dev/null +++ b/Box42/WindowButton/View/WindowViewGroup.swift @@ -0,0 +1,61 @@ +// +// WindowViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import AppKit +import SnapKit + +class WindowViewGroup: NSView { + lazy var windowClose = WindowCloseButton(completion: { self.close?() }) + lazy var windowMinimize = WindowMinimizeButton(completion: { self.minimize?() }) + lazy var windowMaximize = WindowMaximizeButton(completion: { self.maximize?() }) + + var close: (() -> Void)? + var minimize: (() -> Void)? + var maximize: (() -> Void)? + + override init(frame: NSRect) { + super.init(frame: frame) + setupViews() + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + setupConstraints() + } + + private func setupViews() { + self.addSubview(windowClose) + self.addSubview(windowMinimize) + self.addSubview(windowMaximize) + } + + private func setupConstraints() { + + windowClose.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.equalToSuperview() + make.width.equalTo(21) + make.height.equalTo(21) + } + + windowMinimize.snp.makeConstraints { make in + make.top.bottom.equalTo(windowClose) + make.left.equalTo(windowClose.snp.right).offset(7) + make.width.equalTo(21) + make.height.equalTo(21) + } + + windowMaximize.snp.makeConstraints { make in + make.top.bottom.equalTo(windowClose) + make.left.equalTo(windowMinimize.snp.right).offset(7) + make.width.equalTo(21) + make.height.equalTo(21) + } + } +} diff --git a/Box42/WindowButton/WindowButtonViewController.swift b/Box42/WindowButton/WindowButtonViewController.swift new file mode 100644 index 0000000..10dd411 --- /dev/null +++ b/Box42/WindowButton/WindowButtonViewController.swift @@ -0,0 +1,38 @@ +// +// WindowButtonViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/23/23. +// + +import Cocoa + +class WindowButtonViewController: NSViewController { + override func loadView() { + let windowViewGroup = WindowViewGroup() + + windowViewGroup.close = windowClose + windowViewGroup.minimize = windowMin + windowViewGroup.maximize = windowMax + + self.view = windowViewGroup + } + + override func viewDidLoad() { + super.viewDidLoad() + } + + func windowClose() { + StateManager.shared.showWindow = false + self.view.window?.close() + } + + func windowMin() { + StateManager.shared.showWindow = false + self.view.window?.miniaturize(nil) + } + + func windowMax() { + self.view.window?.toggleFullScreen(nil) + } +} From a6825a24dd879e86c6822cdfd341dfa1de86479f Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:20:31 +0900 Subject: [PATCH 17/33] =?UTF-8?q?refactor:=20code=20style=EC=9D=84=20?= =?UTF-8?q?=EA=B6=8C=EC=9E=A5=EB=90=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Extensions/NSScreen.swift | 10 +++- Box42/Menubar/MenubarViewController.swift | 7 +-- Box42/Scripts/Scripts.swift | 4 +- Box42/Shared/BoxSizeManager.swift | 8 +-- Box42/Shared/Constants.swift | 8 ++- Box42/Shared/StateManager.swift | 71 +++++++++++------------ Box42/System/CPU.swift | 2 +- Box42/WebView/WebView.swift | 5 +- 8 files changed, 59 insertions(+), 56 deletions(-) diff --git a/Box42/Extensions/NSScreen.swift b/Box42/Extensions/NSScreen.swift index 778e4fd..263a718 100644 --- a/Box42/Extensions/NSScreen.swift +++ b/Box42/Extensions/NSScreen.swift @@ -10,7 +10,13 @@ import Cocoa extension NSScreen { static let screenSize = NSScreen.main?.visibleFrame.size static let screenWidth = screenSize!.width - static let screenHeight = screenSize!.height + static let screenHeight = screenSize!.height - 60 static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) - static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) + static let contentsScreenSize = CGSize(width: CGFloat(768), height: screenHeight) + static let buttonGroupSize = CGSize(width: CGFloat(200), height: screenHeight) + static let customScreenSize = contentsScreenSize + buttonGroupSize +} + +func +(left: CGSize, right: CGSize) -> CGSize { + return CGSize(width: left.width + right.width, height: left.height) } diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 7a8a719..2701716 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -21,7 +21,7 @@ class MenubarViewController: NSViewController { func menubarViewControllerStart() { self.menubarStartRunning() self.buttonActionInit() - self.popoverCoentViewInit() + self.popoverContentViewInit() self.startEventMonitoring() } @@ -42,7 +42,7 @@ class MenubarViewController: NSViewController { } func buttonInit() { - buttonImageChange("Cat") + buttonImageChange("Fox") statusBarVM.statusButtonAppear() } @@ -55,7 +55,7 @@ class MenubarViewController: NSViewController { statusBarVM.statusBar.statusItem.button?.target = self } - func popoverCoentViewInit() { + func popoverContentViewInit() { let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) popover.contentViewController = boxViewController } @@ -125,7 +125,6 @@ extension MenubarViewController: MenubarViewControllerDelegate { boxWindowController?.showWindow(sender) } } - } protocol MenubarViewControllerDelegate: AnyObject { diff --git a/Box42/Scripts/Scripts.swift b/Box42/Scripts/Scripts.swift index 96323f7..2feac26 100644 --- a/Box42/Scripts/Scripts.swift +++ b/Box42/Scripts/Scripts.swift @@ -8,8 +8,8 @@ import Foundation struct Scripts { - var info: [(name: String, description: String)] = [("cleanCache", "cleaning cache"), ("brewInGoinfre", - "brew download in goinfre")] + var info: [(name: String, description: String)] = [("cleanCache", "cleaning cache"), + ("brewInGoinfre", "brew download in goinfre")] } struct Script { diff --git a/Box42/Shared/BoxSizeManager.swift b/Box42/Shared/BoxSizeManager.swift index acd32f4..1e80c2b 100644 --- a/Box42/Shared/BoxSizeManager.swift +++ b/Box42/Shared/BoxSizeManager.swift @@ -22,13 +22,13 @@ struct BoxSizeManager { init() { halfSize = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) - size = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) - buttonGroupSize = (CGFloat(132), NSScreen.customScreenSize.y) - toolbarGroupSize = (CGFloat(132), CGFloat(100)) + size = (NSScreen.customScreenSize.width, NSScreen.customScreenSize.height) + buttonGroupSize = (NSScreen.buttonGroupSize.width, NSScreen.buttonGroupSize.height) + toolbarGroupSize = (NSScreen.buttonGroupSize.width, CGFloat(100)) viewStack = [NSView()] boxViewSizeNSRect = NSRect(x: 0, y: 0, width: size.width, height: size.height) boxViewSizeNSSize = NSSize(width: size.width, height: size.height) buttonGroupSizeNSRect = NSRect(x: 0, y: 0, width: buttonGroupSize.width, height: buttonGroupSize.height) - windowButtonGroupSize = (CGFloat(200), NSScreen.customScreenSize.y) + windowButtonGroupSize = (NSScreen.buttonGroupSize.width, NSScreen.customScreenSize.height) } } diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift index 322faa9..4484e4a 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -7,11 +7,13 @@ struct Constants { struct url { - static let InitialName = "home" - static let InitialPage = "https://42box.github.io/front-end/" + static let initialName = "home" + static let initialPage = "https://42box.github.io/front-end/" } struct UI { - static let GroupAutolayout = 12 + static let groupAutolayout = 16 + static let topWindow = 64 - 16 + static let leadingWindow = 14 } } diff --git a/Box42/Shared/StateManager.swift b/Box42/Shared/StateManager.swift index e73da57..e62b1e3 100644 --- a/Box42/Shared/StateManager.swift +++ b/Box42/Shared/StateManager.swift @@ -7,62 +7,59 @@ class StateManager { static let shared = StateManager() - - private var isPin: Bool! - private var isShowCPUUsage: Bool! - private var isShowWindow: Bool! - private var isShowFirstWindow: Bool! - private var isAutoStorage: Bool! - private init() { - isPin = false - isShowCPUUsage = false - isShowWindow = false - isShowFirstWindow = false - isAutoStorage = true - } + private var _pin: Bool = false + private var _showCPUUsage: Bool = false + private var _showWindow: Bool = false + private var _showFirstWindow: Bool = false + private var _autoStorage: Bool = true - func getIsPin() -> Bool { - return isPin + var pin: Bool { + get { return _pin } + set { _pin = newValue } } - func setToggleIsPin() { - isPin.toggle() + func togglePin() { + _pin.toggle() } - func getIsShowCPUUsage() -> Bool { - return isShowCPUUsage + var showCPUUsage: Bool { + get { return _showCPUUsage } + set { _showCPUUsage = newValue } } - - func setToggleIsShowCPUUsage() { - isShowCPUUsage.toggle() + + func toggleShowCPUUsage() { + _showCPUUsage.toggle() } - func getIsShowWindow() -> Bool { - return isShowWindow + var showWindow: Bool { + get { return _showWindow } + set { _showWindow = newValue } } - func setToggleIsShowWindow() { - isShowWindow.toggle() + func toggleShowWindow() { + _showWindow.toggle() } - func getIsShowFirstWindow() -> Bool { - return isShowFirstWindow + var showFirstWindow: Bool { + get { return _showFirstWindow } + set { _showFirstWindow = newValue } } - - func setToggleIsShowFirstWindow() { - isShowFirstWindow.toggle() + + func toggleShowFirstWindow() { + _showFirstWindow.toggle() } - func getIsAutoStorage() -> Bool { - return isAutoStorage + var autoStorage: Bool { + get { return _autoStorage } + set { _autoStorage = newValue } } - func setOffIsAutoStorage() { - isAutoStorage = false + func setOffAutoStorage() { + _autoStorage = false } - func setOnIsAutoStorage() { - isAutoStorage = true + func setOnAutoStorage() { + _autoStorage = true } } diff --git a/Box42/System/CPU.swift b/Box42/System/CPU.swift index f7a8dbf..9f70003 100644 --- a/Box42/System/CPU.swift +++ b/Box42/System/CPU.swift @@ -52,7 +52,7 @@ class CPU { cpuTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true, block: { _ in self.usageCPU() statusBar.interval = 0.02 * (100 - max(0.0, min(99.0, self.usage.value))) / 6 - statusBar.statusItem.button?.title = StateManager.shared.getIsShowCPUUsage() ? self.usage.description : "" + statusBar.statusItem.button?.title = StateManager.shared.showCPUUsage ? self.usage.description : "" }) self.cpuTimer?.fire() return true diff --git a/Box42/WebView/WebView.swift b/Box42/WebView/WebView.swift index 0e909ad..e12930e 100644 --- a/Box42/WebView/WebView.swift +++ b/Box42/WebView/WebView.swift @@ -7,7 +7,7 @@ import WebKit -class WebView: WKWebView, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { +class WebView: WKWebView, WKScriptMessageHandler, WKUIDelegate { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { print("userContentController") } @@ -25,14 +25,13 @@ class WebView: WKWebView, WKScriptMessageHandler, WKUIDelegate, WKNavigationDele super.init(frame: .zero, configuration: configuration) - contentController.add(self, name: "box") // Moved after super.init + contentController.add(self, name: "box") self.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true self.configuration.preferences.javaScriptEnabled = true self.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") self.uiDelegate = self - self.navigationDelegate = self self.becomeFirstResponder() } From 69453e60d952aae6ad34c8cab2fe181d122a468f Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:20:59 +0900 Subject: [PATCH 18/33] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=EC=97=90=20=EB=A7=9E=EC=B6=B0=EC=84=9C=20?= =?UTF-8?q?=EC=9E=AC=EC=A1=B0=EB=A6=BD=20=ED=95=98=EC=98=80=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Toolbar/View/BoxToolbarViewGroup.swift | 64 +++++++------- Box42/Toolbar/View/DisplayURLInToolbar.swift | 84 +++++++++++++++++-- Box42/Toolbar/View/DisplayURLTextfield.swift | 26 ++++++ Box42/Toolbar/View/GoBackInToolbar.swift | 6 +- Box42/Toolbar/View/GoForwardInToolbar.swift | 6 +- .../Toolbar/View/GoHomePageViaToolbar().swift | 4 +- .../Toolbar/View/RefreshPageViaToolbar.swift | 6 +- Box42/Toolbar/View/SideBarLeading.swift | 6 +- 8 files changed, 155 insertions(+), 47 deletions(-) create mode 100644 Box42/Toolbar/View/DisplayURLTextfield.swift diff --git a/Box42/Toolbar/View/BoxToolbarViewGroup.swift b/Box42/Toolbar/View/BoxToolbarViewGroup.swift index 6495f30..00628df 100644 --- a/Box42/Toolbar/View/BoxToolbarViewGroup.swift +++ b/Box42/Toolbar/View/BoxToolbarViewGroup.swift @@ -9,12 +9,12 @@ import AppKit import SnapKit class BoxToolbarViewGroup: NSView { - var displayURL = DisplayURLInToolbar() - lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "sidebar.leading"), completion: { self.sidebar?() }) - lazy var goBackButton: GoBackInToolbar = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow.left"), completion: { self.goBack?() }) - lazy var goForwardButton: GoForwardInToolbar = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow.right"), completion: { self.goFoward?()} ) - lazy var reloadPageButton: ReloadPageViaToolbar = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "arrow.clockwise"), completion: { self.reloadPage?() }) - lazy var goHomePageViaButton: GoHomePageViaToolbar = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: { self.goToHome?() }) + var displayURL: DisplayURLInToolbar = DisplayURLInToolbar() + lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "toggle-off"), completion: { [weak self] in self?.sidebar?() }) + lazy var goBackButton: GoBackInToolbar = GoBackInToolbar(image: NSImage(imageLiteralResourceName: "arrow-left"), completion: { [weak self] in self?.goBack?() }) + lazy var goForwardButton: GoForwardInToolbar = GoForwardInToolbar(image: NSImage(imageLiteralResourceName: "arrow-right"), completion: { [weak self] in self?.goFoward?()} ) + lazy var reloadPageButton: ReloadPageViaToolbar = ReloadPageViaToolbar(image: NSImage(imageLiteralResourceName: "rotate-right"), completion: { [weak self] in self?.reloadPage?() }) + lazy var goHomePageViaButton: GoHomePageViaToolbar = GoHomePageViaToolbar(image: NSImage(imageLiteralResourceName: "figure.skating"), completion: { [weak self] in self?.goToHome?() }) var goBack: (() -> Void)? var goFoward: (() -> Void)? @@ -35,49 +35,47 @@ class BoxToolbarViewGroup: NSView { } private func setupViews() { - self.addSubview(displayURL) - self.addSubview(sidebarLeading) self.addSubview(goBackButton) self.addSubview(goForwardButton) self.addSubview(reloadPageButton) - self.addSubview(goHomePageViaButton) + self.addSubview(sidebarLeading) + self.addSubview(displayURL) +// self.addSubview(goHomePageViaButton) } private func setupConstraints() { - displayURL.snp.makeConstraints { make in - make.top.equalToSuperview() - make.left.right.equalToSuperview() - } - - sidebarLeading.snp.makeConstraints { make in - make.top.equalTo(displayURL.snp.bottom).offset(10) - make.bottom.equalToSuperview() - make.left.equalToSuperview() - make.width.equalTo(goBackButton) - } - goBackButton.snp.makeConstraints { make in - make.top.bottom.equalTo(sidebarLeading) - make.left.equalTo(sidebarLeading.snp.right).offset(10) - make.width.equalTo(goForwardButton) + make.top.equalToSuperview() + make.left.equalToSuperview().offset(2) + make.width.equalTo(24) + make.height.equalTo(24) } goForwardButton.snp.makeConstraints { make in - make.top.bottom.equalTo(sidebarLeading) - make.left.equalTo(goBackButton.snp.right).offset(10) - make.width.equalTo(reloadPageButton) + make.top.bottom.equalTo(goBackButton) + make.left.equalTo(goBackButton.snp.right).offset(14) + make.width.equalTo(24) + make.height.equalTo(24) } reloadPageButton.snp.makeConstraints { make in - make.top.bottom.equalTo(sidebarLeading) - make.left.equalTo(goForwardButton.snp.right).offset(10) - make.width.equalTo(goHomePageViaButton) + make.top.bottom.equalTo(goBackButton) + make.left.equalTo(goForwardButton.snp.right).offset(14) + make.width.equalTo(24) + make.height.equalTo(24) } - goHomePageViaButton.snp.makeConstraints { make in - make.top.bottom.equalTo(sidebarLeading) - make.left.equalTo(reloadPageButton.snp.right).offset(10) + sidebarLeading.snp.makeConstraints { make in + make.top.equalToSuperview() make.right.equalToSuperview() + make.width.equalTo(24) + make.height.equalTo(24) + } + + displayURL.snp.makeConstraints { make in + make.top.equalTo(goBackButton.snp.bottom).offset(14) + make.left.right.equalToSuperview() + make.height.equalTo(44) } } } diff --git a/Box42/Toolbar/View/DisplayURLInToolbar.swift b/Box42/Toolbar/View/DisplayURLInToolbar.swift index d8026dd..59ff65b 100644 --- a/Box42/Toolbar/View/DisplayURLInToolbar.swift +++ b/Box42/Toolbar/View/DisplayURLInToolbar.swift @@ -6,28 +6,94 @@ // import AppKit +import WebKit +import SnapKit -class DisplayURLInToolbar: NSTextField { +class DisplayURLInToolbar: NSView { + var URLTextfield: DisplayURLTextfield = DisplayURLTextfield() + var originalString: String = "" override init(frame frameRect: NSRect) { - super.init(frame: frameRect) + super.init(frame: .zero) + self.wantsLayer = true + self.layer?.backgroundColor = NSColor(hex: "#7FFFFFFF").cgColor + self.layer?.cornerRadius = 13 - self.isEditable = true - self.isBordered = false // 테두리를 제거합니다. - self.backgroundColor = NSColor.clear // 배경색을 투명하게 만듭니다. + WebViewManager.shared.hostingWebView?.navigationDelegate = self - if let url = WebViewManager.shared.hostingWebView?.url { - self.stringValue = url.absoluteString + self.addSubview(URLTextfield) + textfieldInit() + textfieldConstraints() + + updateURL() + } + + func textfieldInit() { + URLTextfield.font = NSFont.systemFont(ofSize: 15) + URLTextfield.maximumNumberOfLines = 1 + URLTextfield.lineBreakMode = .byTruncatingTail + URLTextfield.isEditable = true + URLTextfield.isBordered = false + URLTextfield.backgroundColor = NSColor.clear + URLTextfield.focusRingType = .none + URLTextfield.isAutomaticTextCompletionEnabled = false + URLTextfield.delegate = self + URLTextfield.onTextFieldRestore = { + self.URLTextfield.stringValue = self.originalString } } - + + func textfieldConstraints() { + URLTextfield.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview().offset(17) + make.trailing.equalToSuperview().offset(-17) + } + } + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } +} + +extension DisplayURLInToolbar: NSTextFieldDelegate { + func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool { + if commandSelector == #selector(insertNewline(_:)) { + var urlString = URLTextfield.stringValue + let validateURL = urlString.split(separator: "/").map({String($0)}) + if validateURL.count < 1 { + return false + } else if validateURL[0] != "https:" && validateURL[0] != "http:" { + urlString = "https://" + urlString + } + + if let url = URL(string: urlString) { + DispatchQueue.main.async { + print(url) + WebViewManager.shared.hostingWebView?.load(URLRequest(url: url)) + } + } + return true + } + return false + } +} +extension DisplayURLInToolbar: WKNavigationDelegate { func updateURL() { if let url = WebViewManager.shared.hostingWebView?.url { - self.stringValue = url.absoluteString + originalString = url.absoluteString + let showURLString: [String?] = originalString.split(separator: "/").map{String($0)} + if showURLString.count > 1 { + URLTextfield.stringValue = (showURLString[1] ?? "") + } } } } + +extension DisplayURLInToolbar { + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + print("Navigation finished") + updateURL() + } +} diff --git a/Box42/Toolbar/View/DisplayURLTextfield.swift b/Box42/Toolbar/View/DisplayURLTextfield.swift new file mode 100644 index 0000000..ea65859 --- /dev/null +++ b/Box42/Toolbar/View/DisplayURLTextfield.swift @@ -0,0 +1,26 @@ +// +// DisplayURLTextfield.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import AppKit + +class DisplayURLTextfield: NSTextField { + var onTextFieldRestore: (() -> Void)? + + override func mouseDown(with event: NSEvent) { + onTextFieldRestore?() + super.mouseDown(with: event) + } + + override func keyUp(with event: NSEvent) { + if event.keyCode == 53 { + print("url") + onTextFieldRestore?() + } else { + super.keyUp(with: event) + } + } +} diff --git a/Box42/Toolbar/View/GoBackInToolbar.swift b/Box42/Toolbar/View/GoBackInToolbar.swift index 6bb209f..9e3a8c3 100644 --- a/Box42/Toolbar/View/GoBackInToolbar.swift +++ b/Box42/Toolbar/View/GoBackInToolbar.swift @@ -15,10 +15,14 @@ class GoBackInToolbar: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(goBackWebView) self.callback = completion + self.wantsLayer = true + self.layer?.backgroundColor = .clear } required init?(coder: NSCoder) { diff --git a/Box42/Toolbar/View/GoForwardInToolbar.swift b/Box42/Toolbar/View/GoForwardInToolbar.swift index e5f04fb..5556d05 100644 --- a/Box42/Toolbar/View/GoForwardInToolbar.swift +++ b/Box42/Toolbar/View/GoForwardInToolbar.swift @@ -15,10 +15,14 @@ class GoForwardInToolbar: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(goForwardWebView) self.callback = completion + self.wantsLayer = true + self.layer?.backgroundColor = .clear } required init?(coder: NSCoder) { diff --git a/Box42/Toolbar/View/GoHomePageViaToolbar().swift b/Box42/Toolbar/View/GoHomePageViaToolbar().swift index 2728ff3..c647cc1 100644 --- a/Box42/Toolbar/View/GoHomePageViaToolbar().swift +++ b/Box42/Toolbar/View/GoHomePageViaToolbar().swift @@ -15,7 +15,9 @@ class GoHomePageViaToolbar: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(goToHomePageWebView) self.callback = completion diff --git a/Box42/Toolbar/View/RefreshPageViaToolbar.swift b/Box42/Toolbar/View/RefreshPageViaToolbar.swift index 8be72bc..8c4ef50 100644 --- a/Box42/Toolbar/View/RefreshPageViaToolbar.swift +++ b/Box42/Toolbar/View/RefreshPageViaToolbar.swift @@ -15,7 +15,11 @@ class ReloadPageViaToolbar: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor + self.wantsLayer = true + self.layer?.backgroundColor = .clear self.target = self self.action = #selector(reloadWebView) self.callback = completion diff --git a/Box42/Toolbar/View/SideBarLeading.swift b/Box42/Toolbar/View/SideBarLeading.swift index 9849a05..24c2f1c 100644 --- a/Box42/Toolbar/View/SideBarLeading.swift +++ b/Box42/Toolbar/View/SideBarLeading.swift @@ -15,10 +15,14 @@ class SideBarLeading: NSButton { super.init(frame: .zero) self.image = image - self.bezelStyle = .texturedRounded + self.isBordered = false // 버튼의 테두리를 제거 + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(sideBarLeading) self.callback = completion + self.wantsLayer = true + self.layer?.backgroundColor = .clear } required init?(coder: NSCoder) { From 8900553936901b70eef94c8f954d867d80020b0c Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:21:22 +0900 Subject: [PATCH 19/33] =?UTF-8?q?refactor:=20code=20style=EC=9D=84=20?= =?UTF-8?q?=EA=B6=8C=EC=9E=A5=EB=90=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/System/Storage.swift | 7 +++---- Box42/UI/MovableContainerView.swift | 2 +- Box42/WebView/WebViewModel.swift | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Box42/System/Storage.swift b/Box42/System/Storage.swift index 4024446..a728ffb 100644 --- a/Box42/System/Storage.swift +++ b/Box42/System/Storage.swift @@ -55,7 +55,7 @@ class Storage { func storageTimerEvent(){ storageTimer?.invalidate() - if StateManager.shared.getIsAutoStorage() == false { + if StateManager.shared.autoStorage == false { return } @@ -72,7 +72,7 @@ class Storage { if usagePercentage < self.config.threshold.rawValue { self.cleanSh() self.count += 1 - if self.count > 2 { + if self.count > 1 { // showMessageWithAppleScript("캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요.", "재시작") { button in // print("timer") // dump(button) @@ -89,8 +89,7 @@ class Storage { // } // } // } - StateManager.shared.setOffIsAutoStorage() - // 여기서도 타이머를 중지시켜야 합니다. + StateManager.shared.setOffAutoStorage() self.storageTimer?.invalidate() } else { print("\(usedUsage.roundedToTwoDecimalPlaces) GB", "Storage used is less than 30%") diff --git a/Box42/UI/MovableContainerView.swift b/Box42/UI/MovableContainerView.swift index 69c4042..bd8dba6 100644 --- a/Box42/UI/MovableContainerView.swift +++ b/Box42/UI/MovableContainerView.swift @@ -9,7 +9,7 @@ import AppKit class MovableContainerView: NSView { init() { - super.init(frame: NSRect(x: 0, y: 0, width: 300, height: BoxSizeManager.shared.size.height)) + super.init(frame: .zero) } required init?(coder: NSCoder) { diff --git a/Box42/WebView/WebViewModel.swift b/Box42/WebView/WebViewModel.swift index 2e091a0..d9af17b 100644 --- a/Box42/WebView/WebViewModel.swift +++ b/Box42/WebView/WebViewModel.swift @@ -17,7 +17,7 @@ class WebViewModel: ObservableObject { private var cancellables = Set() init() { - self.webViewURL = URLModels(info: [URLModel(name: Constants.url.InitialName, url: Constants.url.InitialPage)]) + self.webViewURL = URLModels(info: [URLModel(name: Constants.url.initialName, url: Constants.url.initialPage)]) self.URLdict = URLMapping() $webViewURL.sink { (WVURL) in @@ -43,11 +43,11 @@ class WebViewModel: ObservableObject { } func readURL(_ index: Int) -> URL { - return URL(string: webViewURL.info[index].url) ?? URL(string: Constants.url.InitialPage)! + return URL(string: webViewURL.info[index].url) ?? URL(string: Constants.url.initialPage)! } func safeURL() -> URL { - return URL(string: webViewURL.info.first?.url ?? Constants.url.InitialPage)! + return URL(string: webViewURL.info.first?.url ?? Constants.url.initialPage)! } func requestURL(_ url: URL) -> URLRequest { From 8f700c2aa991a3de0cef8970a3ed435de063df44 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:21:37 +0900 Subject: [PATCH 20/33] =?UTF-8?q?feat:=20=EC=83=81=EB=8B=A8=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=EC=9D=84=20Fox=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.=20=F0=9F=A6=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Menubar/MenubarViewModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index 7a7fb9e..5d23f10 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -31,6 +31,7 @@ class StatusBarViewModel { case "gam": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gam_\(i)"))} case "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "lee_\(i)"))} case "Box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(i)"))} + case "Fox": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "fox_page\(i)"))} case "box_oc": for i in (1...2) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_oc\(i)"))} default : for i in (1...11) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42flip_0\(i)"))} } From 246071b5523273f797eb56ca2b6208bb7bebac6c Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 25 Aug 2023 06:22:07 +0900 Subject: [PATCH 21/33] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=A1=B0=EB=A5=BC?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/BoxBaseContainerViewController.swift | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/Box42/Main/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift index e07a11e..dcb6323 100644 --- a/Box42/Main/BoxBaseContainerViewController.swift +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -13,9 +13,9 @@ class BoxBaseContainerViewController: NSViewController { var contentGroup: BoxContentsViewGroup = BoxContentsViewGroup() var toolbarGroupVC: ToolbarViewController = ToolbarViewController() var functionGroupVC: BoxFunctionViewController = BoxFunctionViewController() - let windowViewGroup: WindowButtonViewController = WindowButtonViewController() - var buttonGroup: BoxButtonViewGroup! - var leftContainer: MovableContainerView! + let windowViewGroupVC: WindowButtonViewController = WindowButtonViewController() + var leftContainer: MovableContainerView = MovableContainerView() + var buttonGroupVC: ButtonGroupViewController = ButtonGroupViewController() weak var menubarVCDelegate: MenubarViewControllerDelegate? // extension override func loadView() { @@ -23,7 +23,7 @@ class BoxBaseContainerViewController: NSViewController { self.view.addSubview(splitView) splitView.delegate = self - buttonGroup = BoxButtonViewGroupInit() +// buttonGroup = BoxButtonViewGroupInit() leftContainerInit() viewInit() @@ -69,39 +69,44 @@ class BoxBaseContainerViewController: NSViewController { } private func leftContainerInit() { - leftContainer = MovableContainerView() - leftContainer.addSubview(buttonGroup) - leftContainer.addSubview(windowViewGroup.view) + leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width + leftContainer.frame.size.height = BoxSizeManager.shared.windowButtonGroupSize.height +// leftContainer.addSubview(windowViewGroupVC.view) + leftContainer.addSubview(buttonGroupVC.view) leftContainer.addSubview(toolbarGroupVC.view) leftContainer.addSubview(functionGroupVC.view) + leftContainerAutolayout() - leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width } private func leftContainerAutolayout() { - windowViewGroup.view.snp.makeConstraints { make in - make.top.equalTo(leftContainer).offset(Constants.UI.GroupAutolayout) - make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) - make.left.equalTo(leftContainer) - } +// windowViewGroupVC.view.snp.makeConstraints { make in +// make.top.equalTo(leftContainer) +// make.left.equalTo(leftContainer).offset(3) +// make.width.equalTo(77) +// make.height.equalTo(21) +// } toolbarGroupVC.view.snp.makeConstraints { make in - make.top.equalTo(windowViewGroup.view.snp.bottom).offset(Constants.UI.GroupAutolayout) - make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) - make.left.equalTo(leftContainer) - } - - buttonGroup.snp.makeConstraints { make in - make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.GroupAutolayout) - make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) +// make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) + make.top.equalTo(leftContainer).offset(31) // wVGVC 없으면 + make.right.equalTo(leftContainer) make.left.equalTo(leftContainer) + make.height.equalTo(44 + 14 + 24) } functionGroupVC.view.snp.makeConstraints { make in - make.top.equalTo(buttonGroup.snp.bottom).offset(Constants.UI.GroupAutolayout) - make.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) +// make.top.equalTo(buttonGroup.snp.bottom).offset(Constants.UI.groupAutolayout) + make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) make.left.bottom.equalTo(leftContainer) } + + buttonGroupVC.view.snp.makeConstraints { make in + make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) + make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) + make.left.equalTo(leftContainer) + make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) + } } func viewInit() { @@ -112,10 +117,10 @@ class BoxBaseContainerViewController: NSViewController { self.view.addSubview(splitView) splitView.snp.makeConstraints { make in - make.top.equalTo(self.view).offset(Constants.UI.GroupAutolayout) - make.left.equalTo(self.view).offset(Constants.UI.GroupAutolayout) - make.right.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) - make.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) + make.top.equalToSuperview().offset(Constants.UI.groupAutolayout) + make.left.equalToSuperview().offset(Constants.UI.groupAutolayout) + make.right.equalToSuperview().offset(-Constants.UI.groupAutolayout) + make.bottom.equalToSuperview().offset(-Constants.UI.groupAutolayout) } } @@ -155,6 +160,6 @@ extension BoxBaseContainerViewController: NSSplitViewDelegate { extension BoxBaseContainerViewController: BoxFunctionViewControllerDelegate { func didTapBoxButton() { - clickBtn(sender: "box") // 여기에 적절한 sender (NSButton) 전달) + clickBtn(sender: "box") } } From f8824d683a7a3ae667fe20b9cfcaaec9421caadc Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Sun, 27 Aug 2023 00:49:07 +0900 Subject: [PATCH 22/33] =?UTF-8?q?fix:=20pin=20button=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EB=B3=80=EA=B2=BD=20(#78)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: pin button 디자인 변경 * fix: pin button font 및 label 추가 --- .../Model/FunctionButtonUI.swift | 21 ++++++++++ .../View/BoxFunctionViewGroup.swift | 38 +++++++++--------- Box42/FunctionButton/View/PinButtonView.swift | 18 ++++++++- .../Pin icon-1.imageset/Contents.json | 21 ++++++++++ .../Pin icon-1.imageset/Pin icon.png | Bin 0 -> 649 bytes .../uibuttons/Pin icon.imageset/Contents.json | 21 ++++++++++ .../Pin icon.imageset/Pin icon_45.png | Bin 0 -> 1105 bytes .../Assets.xcassets/uibuttons/Pin icon.png | Bin 0 -> 649 bytes 8 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 Box42/FunctionButton/Model/FunctionButtonUI.swift create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Pin icon.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Pin icon_45.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon.png diff --git a/Box42/FunctionButton/Model/FunctionButtonUI.swift b/Box42/FunctionButton/Model/FunctionButtonUI.swift new file mode 100644 index 0000000..ebad572 --- /dev/null +++ b/Box42/FunctionButton/Model/FunctionButtonUI.swift @@ -0,0 +1,21 @@ +// +// FunctionButtonUI.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit + +struct FunctionButtonUI { + struct size { + static let font: CGFloat = 14 + } + + struct animation { + } + + struct color { + static let pinText = NSColor(hex: "#696969") + } +} diff --git a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift index 2570826..60a96bd 100644 --- a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -10,7 +10,7 @@ import SnapKit class BoxFunctionViewGroup: NSView { lazy var preferenceButton: PreferenceButtonView = PreferenceButtonView(image: NSImage(imageLiteralResourceName: "plus"), completion: { self.preferenceAction?() }) - lazy var pinButton: PinButtonView = PinButtonView(image: NSImage(imageLiteralResourceName: "pin"), completion: { self.pinAction?() }) + lazy var pinButton: PinButtonView = PinButtonView(image: NSImage(imageLiteralResourceName: "Pin icon"), completion: { self.pinAction?() }) lazy var quitButton: QuitButtonView = QuitButtonView(image: NSImage(imageLiteralResourceName: "figure.snowboarding"), completion: { self.quitAction?() }) lazy var boxButton: BoxFunctionButtonView = BoxFunctionButtonView(image: NSImage(imageLiteralResourceName: "shippingbox"), completion: { self.boxAction?() }) lazy var divider: NSBox = TopDivider(completion: { self.dividerAction?() }) @@ -47,29 +47,29 @@ class BoxFunctionViewGroup: NSView { make.left.right.equalToSuperview() } - preferenceButton.snp.makeConstraints { make in + pinButton.snp.makeConstraints { make in make.top.equalTo(divider).offset(10) make.bottom.equalToSuperview() make.left.equalToSuperview() make.width.equalTo(pinButton) } - pinButton.snp.makeConstraints { make in - make.top.bottom.equalTo(preferenceButton) - make.left.equalTo(preferenceButton.snp.right).offset(10) - make.width.equalTo(quitButton) - } - - quitButton.snp.makeConstraints { make in - make.top.bottom.equalTo(preferenceButton) - make.left.equalTo(pinButton.snp.right).offset(10) - make.width.equalTo(boxButton) - } - - boxButton.snp.makeConstraints { make in - make.top.bottom.equalTo(preferenceButton) - make.left.equalTo(quitButton.snp.right).offset(10) - make.right.equalToSuperview() - } +// preferenceButton.snp.makeConstraints { make in +// make.top.bottom.equalTo(pinButton) +// make.left.equalTo(pinButton.snp.right).offset(10) +// make.width.equalTo(quitButton) +// } +// +// quitButton.snp.makeConstraints { make in +// make.top.bottom.equalTo(pinButton) +// make.left.equalTo(preferenceButton.snp.right).offset(10) +// make.width.equalTo(boxButton) +// } +// +// boxButton.snp.makeConstraints { make in +// make.top.bottom.equalTo(pinButton) +// make.left.equalTo(quitButton.snp.right).offset(10) +// make.right.equalToSuperview() +// } } } diff --git a/Box42/FunctionButton/View/PinButtonView.swift b/Box42/FunctionButton/View/PinButtonView.swift index f80e9d3..ddaa1a4 100644 --- a/Box42/FunctionButton/View/PinButtonView.swift +++ b/Box42/FunctionButton/View/PinButtonView.swift @@ -10,17 +10,33 @@ import AppKit class PinButtonView: NSButton { private var callback: (() -> Void)? + private var pinBoxLabel: NSTextField! init(image: NSImage, completion: @escaping () -> Void) { super.init(frame: .zero) self.image = image - self.isBordered = false // 버튼의 테두리를 제거 + self.isBordered = false self.wantsLayer = true self.layer?.backgroundColor = NSColor.clear.cgColor self.target = self self.action = #selector(pin) self.callback = completion + + pinBoxLabel = NSTextField(labelWithString: "Pin Box") + pinBoxLabel.font = NSFont(name: "Inter", size: FunctionButtonUI.size.font) + pinBoxLabel.textColor = FunctionButtonUI.color.pinText + pinBoxLabel.backgroundColor = NSColor.clear + pinBoxLabel.isBordered = false + + self.addSubview(pinBoxLabel) // 라벨을 버튼에 추가 + + // 레이아웃을 설정 (예: AutoLayout) + pinBoxLabel.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + pinBoxLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor), + pinBoxLabel.leadingAnchor.constraint(equalTo: self.trailingAnchor, constant: 8) + ]) } required init?(coder: NSCoder) { diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json new file mode 100644 index 0000000..7146232 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Pin icon.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Pin icon.png b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Pin icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bd8d62c424f7e530b9397371d74efe6e4a4c7b GIT binary patch literal 649 zcmV;40(Sk0P)I~F!1HFOT0gY>CrC_q8G-M(6_RxvLl=$RA>g~4*Uyzlq>3519RwOXx5 zHZk0jl*{GgPNy@0fFcAmo6QJ*#2BK*VsQZ>B0+Ftu^*xJ4k1J&s8}qD>|hJm(G)^N zg1X)An9UIW=s<|na$t44WRt)x6Z5^9RJk=Q5Dhq5QR2Al}hJu3}^fV3dEN4VYf9J+i7N~0Z(MHeK6K= zZnq6iAw*<3pLSa#wViZ^8t@FOov4C}1aWr6mav7JNKv&*WjT}AIC4i6WTMUy{4!?F zyJnlD$$8d-Jf8CGBu&n<%5o0#niP}srp$ToyE7 zWY5^9lda{{8!rdAD+*kU2^ZxDFAw%dLDM5ZJ*t^9`-WXs4?R00000NkvXXu0mjf+)5pS literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json new file mode 100644 index 0000000..966e93e --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Pin icon_45.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Pin icon_45.png b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Pin icon_45.png new file mode 100644 index 0000000000000000000000000000000000000000..265a5793efc611537d09fd33b77209fecd9613a8 GIT binary patch literal 1105 zcmV-X1g`suP)IF>1A}>jrdv16fJ9)xJVC?Ot?9zwfv|OJm^zYfl|Ujq0cPvS zm`DivJ;k8NwSyi1?iWY8k7U{8XD9gU``z8|&P0l$D2k#eilQirZDuG(Y;JB=u=8eS zW zvaqmlb9HrfPZlXqPJjsSM~y!{J-ImNc57?v3t1#L0zrUs!t)ySdi@sL8d)GW0)aHn zxPq+(k*)*BE=Jy>SPRoAwPoO%799EB;o+fAhRKbSX5fI^aMpLY;d%U-Xvzi5Si_^EYRQ-=(YD+?M1me7GUv0r)@SX5FtEpU+*(B6u$c$V%I1G6Pse3@Zko&;;!!&AzKIZyO znq@;O0zcCsA&jl&10U0j7!nhQ8FM+37-IsBvA{Hi!_kq1FeXsag4eWROrTP!)TV*I zv5ntsHpPC|m_WflDH>6tfaMyk|AaAGa>dG-v)wrw^t7x1-`62QjMt<&dxcPQT(lw! zLUDP71QE@ogMzv%8H({RMDIbgtHIWUt-;d{oADMhXX+%3m9|eHlq)dpL>)9^wJ!#d z_+Geq{Ft+ezqzQ7wIXc?7`(xO6Q*{G-y9( zD$2ixHGw$f!)JIg!#>xJxpcv0RZ7PW31ZWN8WdkNAT~>`w^3u9 z%RrRXnCs#S^22oDtUr(tRxBu}N5>J{mU&JKAmXS+aFYZP7l^HZMmXjqorjogoT~@B z(l2?6uf;}mGsfy$1-<;T#JfOIydhZ}8sV77xyhjJWUVkKJ;j`u&;3ci|C|(QfjUti za?_8d1ku(rw}q?K>fG>~7#xv~kB@)Qlwd0la%kX-e90!Cq9}@@D2k#eilQirqGaVC Xmo&Gts9y(m00000NkvXXu0mjff4l~I literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.png b/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bd8d62c424f7e530b9397371d74efe6e4a4c7b GIT binary patch literal 649 zcmV;40(Sk0P)I~F!1HFOT0gY>CrC_q8G-M(6_RxvLl=$RA>g~4*Uyzlq>3519RwOXx5 zHZk0jl*{GgPNy@0fFcAmo6QJ*#2BK*VsQZ>B0+Ftu^*xJ4k1J&s8}qD>|hJm(G)^N zg1X)An9UIW=s<|na$t44WRt)x6Z5^9RJk=Q5Dhq5QR2Al}hJu3}^fV3dEN4VYf9J+i7N~0Z(MHeK6K= zZnq6iAw*<3pLSa#wViZ^8t@FOov4C}1aWr6mav7JNKv&*WjT}AIC4i6WTMUy{4!?F zyJnlD$$8d-Jf8CGBu&n<%5o0#niP}srp$ToyE7 zWY5^9lda{{8!rdAD+*kU2^ZxDFAw%dLDM5ZJ*t^9`-WXs4?R00000NkvXXu0mjf+)5pS literal 0 HcmV?d00001 From 96fd47678f9a119edaa8be39b3536e8486dc5b53 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sun, 27 Aug 2023 01:12:31 +0900 Subject: [PATCH 23/33] =?UTF-8?q?fix:=20function=20button=20=EA=B2=B9?= =?UTF-8?q?=EC=B9=98=EB=8D=98=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 12 ++++++ .../Model/FunctionButtonUI.swift | 2 + .../View/BoxFunctionViewGroup.swift | 3 +- Box42/FunctionButton/View/PinButtonView.swift | 40 +++++++++++-------- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 337d15f..e5bf7f2 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -73,6 +73,7 @@ DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862DC2A85347400278FCD /* Scripts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862DB2A85347400278FCD /* Scripts.swift */; }; DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862E92A853F7F00278FCD /* BoxWindowController.swift */; }; + DEE0FA9D2A9A56CB00085A65 /* FunctionButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */; }; DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; /* End PBXBuildFile section */ @@ -145,6 +146,7 @@ DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862DB2A85347400278FCD /* Scripts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Scripts.swift; path = Box42/Scripts/Scripts.swift; sourceTree = SOURCE_ROOT; }; DEB862E92A853F7F00278FCD /* BoxWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxWindowController.swift; sourceTree = ""; }; + DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionButtonUI.swift; sourceTree = ""; }; DEF7492E2A85603700D987C8 /* nodeInstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = nodeInstall.sh; sourceTree = ""; }; DEF749312A85657600D987C8 /* NSScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSScreen.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -319,6 +321,7 @@ DE4407F82A923E5B0091937A /* FunctionButton */ = { isa = PBXGroup; children = ( + DEE0FA9B2A9A56BD00085A65 /* Model */, DE4407FC2A923E920091937A /* View */, DE4407F92A923E860091937A /* BoxFunctionViewController.swift */, ); @@ -409,6 +412,14 @@ path = WindowButton; sourceTree = ""; }; + DEE0FA9B2A9A56BD00085A65 /* Model */ = { + isa = PBXGroup; + children = ( + DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */, + ); + path = Model; + sourceTree = ""; + }; DEF749302A85655E00D987C8 /* Extensions */ = { isa = PBXGroup; children = ( @@ -550,6 +561,7 @@ DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, DE24E6352A8FE02A00E29F5D /* MovableContainerView.swift in Sources */, DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, + DEE0FA9D2A9A56CB00085A65 /* FunctionButtonUI.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, DE44081D2A928F760091937A /* TopDivider.swift in Sources */, diff --git a/Box42/FunctionButton/Model/FunctionButtonUI.swift b/Box42/FunctionButton/Model/FunctionButtonUI.swift index ebad572..e5c9522 100644 --- a/Box42/FunctionButton/Model/FunctionButtonUI.swift +++ b/Box42/FunctionButton/Model/FunctionButtonUI.swift @@ -10,6 +10,8 @@ import AppKit struct FunctionButtonUI { struct size { static let font: CGFloat = 14 + static let pinWidth: CGFloat = 89 + static let pinHeight: CGFloat = 27 } struct animation { diff --git a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift index 60a96bd..a0e9d49 100644 --- a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -51,7 +51,8 @@ class BoxFunctionViewGroup: NSView { make.top.equalTo(divider).offset(10) make.bottom.equalToSuperview() make.left.equalToSuperview() - make.width.equalTo(pinButton) + make.width.equalTo(FunctionButtonUI.size.pinWidth) + make.height.equalTo(FunctionButtonUI.size.pinHeight) } // preferenceButton.snp.makeConstraints { make in diff --git a/Box42/FunctionButton/View/PinButtonView.swift b/Box42/FunctionButton/View/PinButtonView.swift index ddaa1a4..684e3be 100644 --- a/Box42/FunctionButton/View/PinButtonView.swift +++ b/Box42/FunctionButton/View/PinButtonView.swift @@ -6,37 +6,43 @@ // import AppKit +import SnapKit -class PinButtonView: NSButton { +class PinButtonView: NSView { private var callback: (() -> Void)? + private var pinBoxButton: NSButton! private var pinBoxLabel: NSTextField! init(image: NSImage, completion: @escaping () -> Void) { super.init(frame: .zero) - self.image = image - self.isBordered = false - self.wantsLayer = true - self.layer?.backgroundColor = NSColor.clear.cgColor - self.target = self - self.action = #selector(pin) - self.callback = completion + pinBoxButton = NSButton(image: image, target: self, action: #selector(pin)) + pinBoxButton.isBordered = false + pinBoxButton.wantsLayer = true + pinBoxButton.layer?.backgroundColor = NSColor.clear.cgColor + + self.addSubview(pinBoxButton) pinBoxLabel = NSTextField(labelWithString: "Pin Box") - pinBoxLabel.font = NSFont(name: "Inter", size: FunctionButtonUI.size.font) - pinBoxLabel.textColor = FunctionButtonUI.color.pinText + pinBoxLabel.font = NSFont(name: "Inter", size: 14) + pinBoxLabel.textColor = NSColor(hex: "#696969") pinBoxLabel.backgroundColor = NSColor.clear pinBoxLabel.isBordered = false - self.addSubview(pinBoxLabel) // 라벨을 버튼에 추가 + self.addSubview(pinBoxLabel) + + pinBoxButton.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerY.equalToSuperview() + } - // 레이아웃을 설정 (예: AutoLayout) - pinBoxLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - pinBoxLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor), - pinBoxLabel.leadingAnchor.constraint(equalTo: self.trailingAnchor, constant: 8) - ]) + pinBoxLabel.snp.makeConstraints { make in + make.left.equalTo(pinBoxButton.snp.right).offset(2) + make.centerY.equalToSuperview() + } + + self.callback = completion } required init?(coder: NSCoder) { From 25a439b07ff37f5d3b331bea07024ac4c8bffe6b Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Sun, 27 Aug 2023 02:26:31 +0900 Subject: [PATCH 24/33] =?UTF-8?q?feat:=20=F0=9F=A6=8A=20window=20buttond?= =?UTF-8?q?=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 96 +++++++++++++++++-- Box42/BoxWindowController.swift | 9 +- Box42/Extensions/NSScreen.swift | 11 ++- .../Extensions/PixelConversion+CGFloat.swift | 22 +++++ Box42/Extensions/RotateImage+NSImage.swift | 28 ++++++ .../Main/BoxBaseContainerViewController.swift | 44 +++++---- Box42/Menubar/MenubarViewController.swift | 2 +- Box42/Menubar/MenubarViewModel.swift | 6 +- Box42/Resources/AppDelegate.swift | 5 +- Box42/Shared/Constants.swift | 3 +- Box42/WindowButton/Model/WindowButtonUI.swift | 27 ++++++ .../WindowButton/View/WindowCloseButton.swift | 48 +++++++--- .../View/WindowMaximizeButton.swift | 48 +++++++--- .../View/WindowMinimizeButton.swift | 48 +++++++--- Box42/WindowButton/View/WindowViewGroup.swift | 16 ++-- 15 files changed, 331 insertions(+), 82 deletions(-) create mode 100644 Box42/Extensions/PixelConversion+CGFloat.swift create mode 100644 Box42/Extensions/RotateImage+NSImage.swift create mode 100644 Box42/WindowButton/Model/WindowButtonUI.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index e5bf7f2..309678c 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -68,12 +68,21 @@ DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F532A591F1400FC3B77 /* PreferencesView.swift */; }; DE874F572A591F2500FC3B77 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F562A591F2500FC3B77 /* Icon.swift */; }; DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* String.swift */; }; + DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */; }; + DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */; }; + DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */; }; + DE98E8472A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */; }; + DE98E84B2A98E03800F8744A /* QuickSlotItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */; }; + DE98E8502A98E06300F8744A /* QuickSlotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */; }; + DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */; }; DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */; }; DEB862D42A85124500278FCD /* cleanCache.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D32A85124500278FCD /* cleanCache.sh */; }; DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862DC2A85347400278FCD /* Scripts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862DB2A85347400278FCD /* Scripts.swift */; }; DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862E92A853F7F00278FCD /* BoxWindowController.swift */; }; - DEE0FA9D2A9A56CB00085A65 /* FunctionButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */; }; + DEE0FA822A99FC1000085A65 /* QuickSlotCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */; }; + DEE0FA8B2A9A0BD500085A65 /* QuickSlotCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */; }; + DEE0FA962A9A554F00085A65 /* FunctionButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */; }; DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; /* End PBXBuildFile section */ @@ -141,12 +150,21 @@ DE874F532A591F1400FC3B77 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; DE874F562A591F2500FC3B77 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; DE874F5E2A5935CC00FC3B77 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; + DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PixelConversion+CGFloat.swift"; sourceTree = ""; }; + DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RotateImage+NSImage.swift"; sourceTree = ""; }; + DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewController.swift; sourceTree = ""; }; + DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotHorizontalStackView.swift; sourceTree = ""; }; + DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotItem.swift; sourceTree = ""; }; + DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewModel.swift; sourceTree = ""; }; + DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowButtonUI.swift; sourceTree = ""; }; DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupViewController.swift; sourceTree = ""; }; DEB862D32A85124500278FCD /* cleanCache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cleanCache.sh; sourceTree = ""; }; DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862DB2A85347400278FCD /* Scripts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Scripts.swift; path = Box42/Scripts/Scripts.swift; sourceTree = SOURCE_ROOT; }; DEB862E92A853F7F00278FCD /* BoxWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxWindowController.swift; sourceTree = ""; }; - DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionButtonUI.swift; sourceTree = ""; }; + DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotCollectionView.swift; sourceTree = ""; }; + DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotCollectionViewItem.swift; sourceTree = ""; }; + DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionButtonUI.swift; sourceTree = ""; }; DEF7492E2A85603700D987C8 /* nodeInstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = nodeInstall.sh; sourceTree = ""; }; DEF749312A85657600D987C8 /* NSScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSScreen.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -195,6 +213,7 @@ DE018C082A509BB500FF0AA3 /* WebView */, DEB862E82A853F6800278FCD /* WindowButton */, DE0A917D2A8F864300D1D6F1 /* Toolbar */, + DE98E8382A98D48700F8744A /* QuickSlot */, DE4407F82A923E5B0091937A /* FunctionButton */, ); path = Box42; @@ -321,7 +340,7 @@ DE4407F82A923E5B0091937A /* FunctionButton */ = { isa = PBXGroup; children = ( - DEE0FA9B2A9A56BD00085A65 /* Model */, + DEE0FA942A9A553A00085A65 /* Model */, DE4407FC2A923E920091937A /* View */, DE4407F92A923E860091937A /* BoxFunctionViewController.swift */, ); @@ -372,6 +391,51 @@ path = Preferences; sourceTree = ""; }; + DE98E8382A98D48700F8744A /* QuickSlot */ = { + isa = PBXGroup; + children = ( + DE98E84E2A98E04F00F8744A /* ViewModel */, + DE98E8492A98E02400F8744A /* Model */, + DE98E8412A98DDEB00F8744A /* View */, + DEE0FA872A9A022100085A65 /* Controller */, + ); + path = QuickSlot; + sourceTree = ""; + }; + DE98E8412A98DDEB00F8744A /* View */ = { + isa = PBXGroup; + children = ( + DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */, + DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */, + ); + path = View; + sourceTree = ""; + }; + DE98E8492A98E02400F8744A /* Model */ = { + isa = PBXGroup; + children = ( + DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */, + DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */, + ); + path = Model; + sourceTree = ""; + }; + DE98E84E2A98E04F00F8744A /* ViewModel */ = { + isa = PBXGroup; + children = ( + DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + DE98E8532A98EA4F00F8744A /* Model */ = { + isa = PBXGroup; + children = ( + DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */, + ); + path = Model; + sourceTree = ""; + }; DE9DA8122A97F1E2001C0D3B /* ButtonGroup */ = { isa = PBXGroup; children = ( @@ -406,16 +470,25 @@ DEB862E82A853F6800278FCD /* WindowButton */ = { isa = PBXGroup; children = ( + DE98E8532A98EA4F00F8744A /* Model */, DE3FF36F2A978A6E009C88EF /* View */, DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */, ); path = WindowButton; sourceTree = ""; }; - DEE0FA9B2A9A56BD00085A65 /* Model */ = { + DEE0FA872A9A022100085A65 /* Controller */ = { + isa = PBXGroup; + children = ( + DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + DEE0FA942A9A553A00085A65 /* Model */ = { isa = PBXGroup; children = ( - DEE0FA9C2A9A56CB00085A65 /* FunctionButtonUI.swift */, + DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */, ); path = Model; sourceTree = ""; @@ -428,6 +501,8 @@ DEF749312A85657600D987C8 /* NSScreen.swift */, DE1F1A302A8BD68F00A88DD8 /* Double.swift */, DE24E63A2A8FE93900E29F5D /* NSImage.swift */, + DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */, + DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */, ); path = Extensions; sourceTree = ""; @@ -517,6 +592,7 @@ DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, + DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */, DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, @@ -524,8 +600,11 @@ DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, + DEE0FA962A9A554F00085A65 /* FunctionButtonUI.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, + DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */, DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */, + DE98E8472A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift in Sources */, DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, @@ -533,13 +612,16 @@ DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, + DEE0FA822A99FC1000085A65 /* QuickSlotCollectionView.swift in Sources */, DE0A91862A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, + DEE0FA8B2A9A0BD500085A65 /* QuickSlotCollectionViewItem.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, + DE98E8502A98E06300F8744A /* QuickSlotViewModel.swift in Sources */, DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, @@ -549,6 +631,7 @@ DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, + DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */, DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */, DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */, DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, @@ -561,10 +644,11 @@ DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, DE24E6352A8FE02A00E29F5D /* MovableContainerView.swift in Sources */, DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, - DEE0FA9D2A9A56CB00085A65 /* FunctionButtonUI.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, DE44081D2A928F760091937A /* TopDivider.swift in Sources */, + DE98E84B2A98E03800F8744A /* QuickSlotItem.swift in Sources */, + DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */, diff --git a/Box42/BoxWindowController.swift b/Box42/BoxWindowController.swift index 3a3babf..fe74981 100644 --- a/Box42/BoxWindowController.swift +++ b/Box42/BoxWindowController.swift @@ -10,7 +10,7 @@ import Cocoa class BoxWindowController: NSWindowController, NSWindowDelegate { override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect - let styleMask: NSWindow.StyleMask = [.resizable, .titled, .fullSizeContentView, .closable, .miniaturizable] + let styleMask: NSWindow.StyleMask = [.resizable, .titled, .fullSizeContentView] let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) super.init(window: windowInstance) windowInstance.delegate = self @@ -20,6 +20,13 @@ class BoxWindowController: NSWindowController, NSWindowDelegate { windowInstance.titleVisibility = .hidden windowInstance.isReleasedWhenClosed = false windowInstance.isMovableByWindowBackground = true + windowInstance.standardWindowButton(.closeButton)?.isHidden = true + windowInstance.standardWindowButton(.miniaturizeButton)?.isHidden = true + windowInstance.standardWindowButton(.zoomButton)?.isHidden = true + + if let zoomButton = windowInstance.standardWindowButton(.zoomButton) { + zoomButton.isHidden = true + } let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController diff --git a/Box42/Extensions/NSScreen.swift b/Box42/Extensions/NSScreen.swift index 263a718..836bb71 100644 --- a/Box42/Extensions/NSScreen.swift +++ b/Box42/Extensions/NSScreen.swift @@ -8,13 +8,18 @@ import Cocoa extension NSScreen { + static let screenSize = NSScreen.main?.visibleFrame.size static let screenWidth = screenSize!.width static let screenHeight = screenSize!.height - 60 static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) - static let contentsScreenSize = CGSize(width: CGFloat(768), height: screenHeight) - static let buttonGroupSize = CGSize(width: CGFloat(200), height: screenHeight) - static let customScreenSize = contentsScreenSize + buttonGroupSize + + static var contentsScreenSize = CGSize(width: CGFloat(768).pointsToPixels(), height: screenHeight) + static let buttonGroupSize = CGSize(width: CGFloat(312).pointsToPixels(), height: screenHeight) + + static var customScreenSize: CGSize { + return contentsScreenSize + buttonGroupSize + } } func +(left: CGSize, right: CGSize) -> CGSize { diff --git a/Box42/Extensions/PixelConversion+CGFloat.swift b/Box42/Extensions/PixelConversion+CGFloat.swift new file mode 100644 index 0000000..9b4f762 --- /dev/null +++ b/Box42/Extensions/PixelConversion+CGFloat.swift @@ -0,0 +1,22 @@ +// +// PixelConversion+CGFloat.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Cocoa + +extension CGFloat { + func pointsToPixels() -> CGFloat { + return self * 1.073 + } + + func pixelsToPoints() -> CGFloat { + return self / 1.073 + } + + static func onePixelInPoints() -> CGFloat { + return CGFloat(1).pixelsToPoints() + } +} diff --git a/Box42/Extensions/RotateImage+NSImage.swift b/Box42/Extensions/RotateImage+NSImage.swift new file mode 100644 index 0000000..1483e86 --- /dev/null +++ b/Box42/Extensions/RotateImage+NSImage.swift @@ -0,0 +1,28 @@ +// +// RotateImage+NSImage.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import Cocoa + +extension NSImage { + func rotated(by degrees: CGFloat) -> NSImage? { + guard let imgRep = self.bestRepresentation(for: NSRect(x: 0, y: 0, width: self.size.width, height: self.size.height), context: nil, hints: nil) else { + return nil + } + + let image = NSImage(size: self.size) + + image.lockFocus() + let ctx = NSGraphicsContext.current?.cgContext + ctx?.translateBy(x: size.width / 2, y: size.height / 2) + ctx?.rotate(by: (degrees * CGFloat.pi) / 180) + ctx?.translateBy(x: -size.width / 2, y: -size.height / 2) + imgRep.draw(in: NSRect(x: 0, y: 0, width: size.width, height: size.height)) + image.unlockFocus() + + return image + } +} diff --git a/Box42/Main/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift index dcb6323..011e26c 100644 --- a/Box42/Main/BoxBaseContainerViewController.swift +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -12,6 +12,7 @@ class BoxBaseContainerViewController: NSViewController { var splitView: BoxBaseSplitView = BoxBaseSplitView() var contentGroup: BoxContentsViewGroup = BoxContentsViewGroup() var toolbarGroupVC: ToolbarViewController = ToolbarViewController() + // var quickSlotGroupVC: QuickSlotViewController = QuickSlotViewController() var functionGroupVC: BoxFunctionViewController = BoxFunctionViewController() let windowViewGroupVC: WindowButtonViewController = WindowButtonViewController() var leftContainer: MovableContainerView = MovableContainerView() @@ -31,7 +32,8 @@ class BoxBaseContainerViewController: NSViewController { override func viewDidLoad() { self.view.wantsLayer = true - self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor +// self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor + self.view.layer?.backgroundColor = NSColor(hex: "#E7E7E7").cgColor } func BoxButtonViewGroupInit() -> BoxButtonViewGroup { @@ -71,42 +73,48 @@ class BoxBaseContainerViewController: NSViewController { private func leftContainerInit() { leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width leftContainer.frame.size.height = BoxSizeManager.shared.windowButtonGroupSize.height -// leftContainer.addSubview(windowViewGroupVC.view) + leftContainer.addSubview(windowViewGroupVC.view) leftContainer.addSubview(buttonGroupVC.view) leftContainer.addSubview(toolbarGroupVC.view) +// leftContainer.addSubview(quickSlotGroupVC.view) leftContainer.addSubview(functionGroupVC.view) leftContainerAutolayout() } private func leftContainerAutolayout() { -// windowViewGroupVC.view.snp.makeConstraints { make in -// make.top.equalTo(leftContainer) -// make.left.equalTo(leftContainer).offset(3) -// make.width.equalTo(77) -// make.height.equalTo(21) -// } + windowViewGroupVC.view.snp.makeConstraints { make in + make.top.equalTo(leftContainer) + make.left.equalTo(leftContainer).offset(3) + make.width.equalTo(77) + make.height.equalTo(21) + } toolbarGroupVC.view.snp.makeConstraints { make in -// make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) - make.top.equalTo(leftContainer).offset(31) // wVGVC 없으면 + make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) make.right.equalTo(leftContainer) make.left.equalTo(leftContainer) make.height.equalTo(44 + 14 + 24) } - functionGroupVC.view.snp.makeConstraints { make in -// make.top.equalTo(buttonGroup.snp.bottom).offset(Constants.UI.groupAutolayout) - make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) - make.left.bottom.equalTo(leftContainer) - } - buttonGroupVC.view.snp.makeConstraints { make in make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) make.left.equalTo(leftContainer) make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) } + +// quickSlotGroupVC.view.snp.makeConstraints { make in +// make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-27) +// make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) +// make.left.equalTo(leftContainer) +// make.height.equalTo(178) +// } + + functionGroupVC.view.snp.makeConstraints { make in + make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) + make.left.bottom.equalTo(leftContainer) + } } func viewInit() { @@ -134,14 +142,14 @@ extension BoxBaseContainerViewController: NSSplitViewDelegate { func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { if dividerIndex == 0 { - return 132 + return CGFloat(132).pointsToPixels() } return proposedMinimumPosition } func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { if dividerIndex == 0 { - return 200 + return CGFloat(312).pointsToPixels() } return proposedMaximumPosition } diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 2701716..e9b361c 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -42,7 +42,7 @@ class MenubarViewController: NSViewController { } func buttonInit() { - buttonImageChange("Fox") + buttonImageChange("fox") statusBarVM.statusButtonAppear() } diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index 5d23f10..b1daf88 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -25,13 +25,13 @@ class StatusBarViewModel { statusBar.frames.removeAll() switch imgName { - case "Cat": for i in (0...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "cat_page\(i)"))} + case "cat": for i in (0...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "cat_page\(i)"))} case "gon": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gon_\(i)"))} case "gun": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gun_\(i)"))} case "gam": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gam_\(i)"))} case "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "lee_\(i)"))} - case "Box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(i)"))} - case "Fox": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "fox_page\(i)"))} + case "box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(i)"))} + case "fox": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "fox_page\(i)"))} case "box_oc": for i in (1...2) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_oc\(i)"))} default : for i in (1...11) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42flip_0\(i)"))} } diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 26df5dd..9bde3d6 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -20,8 +20,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { menubarController.menubarViewControllerStart() // alertAccessibility() // hotkey() - storage.storageTimerEvent() - } + +// storage.storageTimerEvent() + } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift index 4484e4a..5e6347d 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -8,7 +8,8 @@ struct Constants { struct url { static let initialName = "home" - static let initialPage = "https://42box.github.io/front-end/" +// static let initialPage = "https://42box.kr" + static let initialPage = "https://profile.intra.42.fr/" } struct UI { diff --git a/Box42/WindowButton/Model/WindowButtonUI.swift b/Box42/WindowButton/Model/WindowButtonUI.swift new file mode 100644 index 0000000..a9e3bdc --- /dev/null +++ b/Box42/WindowButton/Model/WindowButtonUI.swift @@ -0,0 +1,27 @@ +// +// WindowButtonUI.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import AppKit + +struct WindowButtonUI { + struct size { + static let diameter = 15 + static let cornerRadius = CGFloat(diameter / 2) + static let offset = 8 + } + + struct animation { + static let duration = TimeInterval(0.2) + } + + struct color { + static let maximize = NSColor(hex: "#76DF7A").cgColor + static let minimize = NSColor(hex: "#FFCE51").cgColor + static let close = NSColor(hex: "#F36161").cgColor + static let opacityWhite = NSColor(hex: "#7FFFFFFF").cgColor + } +} diff --git a/Box42/WindowButton/View/WindowCloseButton.swift b/Box42/WindowButton/View/WindowCloseButton.swift index 84074b3..3b5d404 100644 --- a/Box42/WindowButton/View/WindowCloseButton.swift +++ b/Box42/WindowButton/View/WindowCloseButton.swift @@ -12,13 +12,13 @@ class WindowCloseButton: NSButton { private var callback: (() -> Void)? init(completion: @escaping () -> Void) { - super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + super.init(frame: NSRect(x: 0, y: 0, width: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) self.title = "" self.isBordered = false self.wantsLayer = true - self.layer?.cornerRadius = 21 / 2 - self.layer?.backgroundColor = NSColor.white.cgColor + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite self.target = self self.action = #selector(closeAction) self.callback = completion @@ -37,19 +37,41 @@ class WindowCloseButton: NSButton { override func mouseEntered(with event: NSEvent) { super.mouseEntered(with: event) - - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.red.cgColor - }, completionHandler: nil) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.close + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.close + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 } - + override func mouseExited(with event: NSEvent) { super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.close + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.white.cgColor - }, completionHandler: nil) + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius } } diff --git a/Box42/WindowButton/View/WindowMaximizeButton.swift b/Box42/WindowButton/View/WindowMaximizeButton.swift index 5934059..f5a7f3c 100644 --- a/Box42/WindowButton/View/WindowMaximizeButton.swift +++ b/Box42/WindowButton/View/WindowMaximizeButton.swift @@ -12,13 +12,13 @@ class WindowMaximizeButton: NSButton { private var callback: (() -> Void)? init(completion: @escaping () -> Void) { - super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + super.init(frame: NSRect(x: 0, y: 0, width: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) self.title = "" self.isBordered = false self.wantsLayer = true - self.layer?.cornerRadius = 21 / 2 - self.layer?.backgroundColor = NSColor.white.cgColor + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite self.target = self self.action = #selector(maximizeAction) self.callback = completion @@ -37,19 +37,41 @@ class WindowMaximizeButton: NSButton { override func mouseEntered(with event: NSEvent) { super.mouseEntered(with: event) - - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.green.cgColor - }, completionHandler: nil) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.maximize + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.maximize + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 } - + override func mouseExited(with event: NSEvent) { super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.maximize + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.white.cgColor - }, completionHandler: nil) + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius } } diff --git a/Box42/WindowButton/View/WindowMinimizeButton.swift b/Box42/WindowButton/View/WindowMinimizeButton.swift index c628742..4d6537c 100644 --- a/Box42/WindowButton/View/WindowMinimizeButton.swift +++ b/Box42/WindowButton/View/WindowMinimizeButton.swift @@ -12,13 +12,13 @@ class WindowMinimizeButton: NSButton { private var callback: (() -> Void)? init(completion: @escaping () -> Void) { - super.init(frame: NSRect(x: 0, y: 0, width: 21, height: 21)) + super.init(frame: NSRect(x: 0, y: 0, width: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) self.title = "" self.isBordered = false self.wantsLayer = true - self.layer?.cornerRadius = 21 / 2 - self.layer?.backgroundColor = NSColor.white.cgColor + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.minimize self.target = self self.action = #selector(minimizeAction) self.callback = completion @@ -37,19 +37,41 @@ class WindowMinimizeButton: NSButton { override func mouseEntered(with event: NSEvent) { super.mouseEntered(with: event) - - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.yellow.cgColor - }, completionHandler: nil) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.minimize + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.minimize + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 } - + override func mouseExited(with event: NSEvent) { super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.minimize + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration - NSAnimationContext.runAnimationGroup({ (context) in - context.duration = 2 - self.layer?.backgroundColor = NSColor.white.cgColor - }, completionHandler: nil) + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius } } diff --git a/Box42/WindowButton/View/WindowViewGroup.swift b/Box42/WindowButton/View/WindowViewGroup.swift index 9891bcc..15ff801 100644 --- a/Box42/WindowButton/View/WindowViewGroup.swift +++ b/Box42/WindowButton/View/WindowViewGroup.swift @@ -40,22 +40,22 @@ class WindowViewGroup: NSView { windowClose.snp.makeConstraints { make in make.top.equalToSuperview() make.left.equalToSuperview() - make.width.equalTo(21) - make.height.equalTo(21) + make.width.equalTo(WindowButtonUI.size.diameter) + make.height.equalTo(WindowButtonUI.size.diameter) } windowMinimize.snp.makeConstraints { make in make.top.bottom.equalTo(windowClose) - make.left.equalTo(windowClose.snp.right).offset(7) - make.width.equalTo(21) - make.height.equalTo(21) + make.left.equalTo(windowClose.snp.right).offset(WindowButtonUI.size.offset) + make.width.equalTo(WindowButtonUI.size.diameter) + make.height.equalTo(WindowButtonUI.size.diameter) } windowMaximize.snp.makeConstraints { make in make.top.bottom.equalTo(windowClose) - make.left.equalTo(windowMinimize.snp.right).offset(7) - make.width.equalTo(21) - make.height.equalTo(21) + make.left.equalTo(windowMinimize.snp.right).offset(WindowButtonUI.size.offset) + make.width.equalTo(WindowButtonUI.size.diameter) + make.height.equalTo(WindowButtonUI.size.diameter) } } } From 4efefcd6b3effcf2c97c761446ad70f4166aa14f Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sun, 27 Aug 2023 03:09:33 +0900 Subject: [PATCH 25/33] =?UTF-8?q?feat:=20UI=EB=A5=BC=20=EC=9C=84=ED=95=9C?= =?UTF-8?q?=20asset=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 42 +++++++++--------- .../Bookmark.imageset/Bookmark icon.png | Bin 0 -> 539 bytes .../uibuttons/Bookmark.imageset/Contents.json | 21 +++++++++ .../Assets.xcassets/uibuttons/Pin icon.png | Bin 649 -> 0 bytes .../uibuttons/Star.imageset/Contents.json | 21 +++++++++ .../uibuttons/Star.imageset/Star 3.png | Bin 0 -> 926 bytes .../Contents.json | 0 .../Pin icon.png | Bin .../Contents.json | 0 .../Pin icon_45.png | Bin 10 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Bookmark icon.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Contents.json delete mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Pin icon.png create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Star 3.png rename Box42/Resources/Assets.xcassets/uibuttons/{Pin icon-1.imageset => pin-box-ver.imageset}/Contents.json (100%) rename Box42/Resources/Assets.xcassets/uibuttons/{Pin icon-1.imageset => pin-box-ver.imageset}/Pin icon.png (100%) rename Box42/Resources/Assets.xcassets/uibuttons/{Pin icon.imageset => pin-box.imageset}/Contents.json (100%) rename Box42/Resources/Assets.xcassets/uibuttons/{Pin icon.imageset => pin-box.imageset}/Pin icon_45.png (100%) diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 309678c..7044783 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -69,19 +69,19 @@ DE874F572A591F2500FC3B77 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F562A591F2500FC3B77 /* Icon.swift */; }; DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* String.swift */; }; DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */; }; + DE97CA792A9A6F6A001073DE /* QuickSlotHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */; }; + DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */; }; + DE97CA7F2A9A73A9001073DE /* QuickSlotUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */; }; + DE97CA862A9A7404001073DE /* QuickSlotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */; }; + DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */; }; DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */; }; DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */; }; - DE98E8472A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */; }; - DE98E84B2A98E03800F8744A /* QuickSlotItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */; }; - DE98E8502A98E06300F8744A /* QuickSlotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */; }; DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */; }; DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */; }; DEB862D42A85124500278FCD /* cleanCache.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D32A85124500278FCD /* cleanCache.sh */; }; DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862DC2A85347400278FCD /* Scripts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862DB2A85347400278FCD /* Scripts.swift */; }; DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862E92A853F7F00278FCD /* BoxWindowController.swift */; }; - DEE0FA822A99FC1000085A65 /* QuickSlotCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */; }; - DEE0FA8B2A9A0BD500085A65 /* QuickSlotCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */; }; DEE0FA962A9A554F00085A65 /* FunctionButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */; }; DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; /* End PBXBuildFile section */ @@ -151,19 +151,19 @@ DE874F562A591F2500FC3B77 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; DE874F5E2A5935CC00FC3B77 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PixelConversion+CGFloat.swift"; sourceTree = ""; }; + DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewModel.swift; sourceTree = ""; }; + DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonModel.swift; sourceTree = ""; }; + DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotHeaderView.swift; sourceTree = ""; }; + DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotGroupView.swift; sourceTree = ""; }; + DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotUI.swift; sourceTree = ""; }; DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RotateImage+NSImage.swift"; sourceTree = ""; }; DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewController.swift; sourceTree = ""; }; - DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotHorizontalStackView.swift; sourceTree = ""; }; - DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotItem.swift; sourceTree = ""; }; - DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewModel.swift; sourceTree = ""; }; DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowButtonUI.swift; sourceTree = ""; }; DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupViewController.swift; sourceTree = ""; }; DEB862D32A85124500278FCD /* cleanCache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cleanCache.sh; sourceTree = ""; }; DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862DB2A85347400278FCD /* Scripts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Scripts.swift; path = Box42/Scripts/Scripts.swift; sourceTree = SOURCE_ROOT; }; DEB862E92A853F7F00278FCD /* BoxWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxWindowController.swift; sourceTree = ""; }; - DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotCollectionView.swift; sourceTree = ""; }; - DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotCollectionViewItem.swift; sourceTree = ""; }; DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionButtonUI.swift; sourceTree = ""; }; DEF7492E2A85603700D987C8 /* nodeInstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = nodeInstall.sh; sourceTree = ""; }; DEF749312A85657600D987C8 /* NSScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSScreen.swift; sourceTree = ""; }; @@ -350,7 +350,6 @@ DE4407FC2A923E920091937A /* View */ = { isa = PBXGroup; children = ( - DE44081C2A928F760091937A /* TopDivider.swift */, DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */, DE4408012A923EB60091937A /* PinButtonView.swift */, DE4408042A923EC00091937A /* QuitButtonView.swift */, @@ -405,8 +404,9 @@ DE98E8412A98DDEB00F8744A /* View */ = { isa = PBXGroup; children = ( - DE98E8462A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift */, - DEE0FA812A99FC1000085A65 /* QuickSlotCollectionView.swift */, + DE44081C2A928F760091937A /* TopDivider.swift */, + DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */, + DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */, ); path = View; sourceTree = ""; @@ -414,8 +414,8 @@ DE98E8492A98E02400F8744A /* Model */ = { isa = PBXGroup; children = ( - DEE0FA842A99FD1100085A65 /* QuickSlotCollectionViewItem.swift */, - DE98E84A2A98E03800F8744A /* QuickSlotItem.swift */, + DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */, + DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */, ); path = Model; sourceTree = ""; @@ -423,7 +423,7 @@ DE98E84E2A98E04F00F8744A /* ViewModel */ = { isa = PBXGroup; children = ( - DE98E84F2A98E06300F8744A /* QuickSlotViewModel.swift */, + DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -598,37 +598,38 @@ DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, DE3FF3742A978AB8009C88EF /* WindowMaximizeButton.swift in Sources */, DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */, + DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, DEE0FA962A9A554F00085A65 /* FunctionButtonUI.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */, DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */, - DE98E8472A98DE6D00F8744A /* QuickSlotHorizontalStackView.swift in Sources */, DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */, + DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, - DEE0FA822A99FC1000085A65 /* QuickSlotCollectionView.swift in Sources */, DE0A91862A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, - DEE0FA8B2A9A0BD500085A65 /* QuickSlotCollectionViewItem.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, - DE98E8502A98E06300F8744A /* QuickSlotViewModel.swift in Sources */, DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, + DE97CA792A9A6F6A001073DE /* QuickSlotHeaderView.swift in Sources */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, + DE97CA862A9A7404001073DE /* QuickSlotViewModel.swift in Sources */, DE3FF3762A978AB8009C88EF /* WindowCloseButton.swift in Sources */, DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */, DE4408022A923EB60091937A /* PinButtonView.swift in Sources */, DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, + DE97CA7F2A9A73A9001073DE /* QuickSlotUI.swift in Sources */, DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */, @@ -647,7 +648,6 @@ DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, DE44081D2A928F760091937A /* TopDivider.swift in Sources */, - DE98E84B2A98E03800F8744A /* QuickSlotItem.swift in Sources */, DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Bookmark icon.png b/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Bookmark icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fa00ba016b23664c6fe74784f4a56141f1adb01c GIT binary patch literal 539 zcmV+$0_6RPP)2-YtFwB*U3-F;|5*4ETV`qO-iQm_FnLf)^XM zLn)SX7R54~nSvLL*Dw3D#j?#(g$p5-rA{(AEsFd`97-evuR{5Ydz@Z9+fvII@EHS~ z`wJ||OmYs#JBtX10`LmG(ALr{uAkm<^YRf!dowEi^Cmg>uhAiwio$OWH{oBdu(fYuP)!QbrXN~S^(}PHCVzK}k zFeOW4bS+bESaW&OJVp|79>7GZcTF0iUbV*(LvP_Lb;c|)nj1T~M7G>;E!K}!o$LFn zCfj;bi3IH`OyhZQ8bcpyXRcGFX)Qgs(p{}bM#mVve27?yv!3fk9?I~F!1HFOT0gY>CrC_q8G-M(6_RxvLl=$RA>g~4*Uyzlq>3519RwOXx5 zHZk0jl*{GgPNy@0fFcAmo6QJ*#2BK*VsQZ>B0+Ftu^*xJ4k1J&s8}qD>|hJm(G)^N zg1X)An9UIW=s<|na$t44WRt)x6Z5^9RJk=Q5Dhq5QR2Al}hJu3}^fV3dEN4VYf9J+i7N~0Z(MHeK6K= zZnq6iAw*<3pLSa#wViZ^8t@FOov4C}1aWr6mav7JNKv&*WjT}AIC4i6WTMUy{4!?F zyJnlD$$8d-Jf8CGBu&n<%5o0#niP}srp$ToyE7 zWY5^9lda{{8!rdAD+*kU2^ZxDFAw%dLDM5ZJ*t^9`-WXs4?R00000NkvXXu0mjf+)5pS diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Contents.json new file mode 100644 index 0000000..bad711e --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Star 3.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Star 3.png b/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Star 3.png new file mode 100644 index 0000000000000000000000000000000000000000..dcfda9c9b4650087fb48586781ccb22eef6d8f48 GIT binary patch literal 926 zcmV;P17ZA$P)3EFSy;2e$DbBqpr~j3=`O60YSRuzQol3rF$7axtDvP4wRS4?u4oG_1xG z9;DHTF`AYG#28~6dr+dWd~dqb4rRC9cDBGv-t4cL>C5|OzM0M-g@+jP4s()Opc8~F zv*vQ0P6$k9%@`l9#iBz}oJkrOpm1QJNTjqFpIchw}ddDQvFBqnOEY+3B zO~)}CMXOs9x~}!=Sd#e;H(qW@=(sl6;X9U@i&UTXbIb+iBJ&|WF5kUOso4v@jnAAO zpuN5Se2yER=ns<=@e;5QO6>L(sQ z+olEk;{j2)@ycV46!-ki4~j%0WL`f<{Qy$Py+@x9iSiS6K%BGjvoGQx3i-`TR6AjZ z#Dy8wPNIl{t(7)&8EFLTVz-I46(vrt@!8jHMFBx}7dF$uLY(Ibp^HK@)91-Y6jAVP zPX)!<=n(0m%o$$ZwyPIZn1Mn!jDV6GlkMsS6(%~7ONS1W^;cV1LsS@!VG=3g4AKy0 zh$6(DMxyDw=~pMnXzmzBY+110A>U#4;(q`(l75H>a4d+hgeZK3Az5Z}CAqH`fIu5b zl(*hq0+qge$63#z#D)%u5*geTKM^2_kJB#Z3cTo>#8`%d}8~rHlds^pUwGaY9ypXFM;z!c~`mkCBqAy(CcS-62 zLRbrtu@|X(SgODk literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Contents.json similarity index 100% rename from Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Contents.json diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Pin icon.png b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Pin icon.png similarity index 100% rename from Box42/Resources/Assets.xcassets/uibuttons/Pin icon-1.imageset/Pin icon.png rename to Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Pin icon.png diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Contents.json similarity index 100% rename from Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Contents.json diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Pin icon_45.png b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Pin icon_45.png similarity index 100% rename from Box42/Resources/Assets.xcassets/uibuttons/Pin icon.imageset/Pin icon_45.png rename to Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Pin icon_45.png From b158979bb4a227b5bc3792eb7027579a39292a72 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sun, 27 Aug 2023 03:09:48 +0900 Subject: [PATCH 26/33] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20UI=20frame=EC=9D=84=20=EA=B5=AC=EC=84=B1=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/BoxFunctionViewGroup.swift | 11 +-- .../Main/BoxBaseContainerViewController.swift | 18 ++--- .../Controller/QuickSlotViewController.swift | 40 +++++++++++ .../Model/QuickSlotButtonModel.swift | 14 ++++ Box42/QuickSlot/Model/QuickSlotUI.swift | 22 ++++++ Box42/QuickSlot/View/QuickSlotGroupView.swift | 47 +++++++++++++ .../QuickSlot/View/QuickSlotHeaderView.swift | 55 +++++++++++++++ .../View/TopDivider.swift | 0 .../ViewModel/QuickSlotViewModel.swift | 29 ++++++++ Box42/WebView/URL/URLModel.swift | 68 ++++++++++++++++++- 10 files changed, 284 insertions(+), 20 deletions(-) create mode 100644 Box42/QuickSlot/Controller/QuickSlotViewController.swift create mode 100644 Box42/QuickSlot/Model/QuickSlotButtonModel.swift create mode 100644 Box42/QuickSlot/Model/QuickSlotUI.swift create mode 100644 Box42/QuickSlot/View/QuickSlotGroupView.swift create mode 100644 Box42/QuickSlot/View/QuickSlotHeaderView.swift rename Box42/{FunctionButton => QuickSlot}/View/TopDivider.swift (100%) create mode 100644 Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift diff --git a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift index a0e9d49..2e961a0 100644 --- a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -10,10 +10,9 @@ import SnapKit class BoxFunctionViewGroup: NSView { lazy var preferenceButton: PreferenceButtonView = PreferenceButtonView(image: NSImage(imageLiteralResourceName: "plus"), completion: { self.preferenceAction?() }) - lazy var pinButton: PinButtonView = PinButtonView(image: NSImage(imageLiteralResourceName: "Pin icon"), completion: { self.pinAction?() }) + lazy var pinButton: PinButtonView = PinButtonView(image: NSImage(imageLiteralResourceName: "pin-box"), completion: { self.pinAction?() }) lazy var quitButton: QuitButtonView = QuitButtonView(image: NSImage(imageLiteralResourceName: "figure.snowboarding"), completion: { self.quitAction?() }) lazy var boxButton: BoxFunctionButtonView = BoxFunctionButtonView(image: NSImage(imageLiteralResourceName: "shippingbox"), completion: { self.boxAction?() }) - lazy var divider: NSBox = TopDivider(completion: { self.dividerAction?() }) var preferenceAction: (() -> Void)? var pinAction: (() -> Void)? @@ -38,17 +37,11 @@ class BoxFunctionViewGroup: NSView { self.addSubview(pinButton) self.addSubview(quitButton) self.addSubview(boxButton) - self.addSubview(divider) } private func setupConstraints() { - divider.snp.makeConstraints { make in - make.top.equalToSuperview() - make.left.right.equalToSuperview() - } - pinButton.snp.makeConstraints { make in - make.top.equalTo(divider).offset(10) + make.top.equalToSuperview() make.bottom.equalToSuperview() make.left.equalToSuperview() make.width.equalTo(FunctionButtonUI.size.pinWidth) diff --git a/Box42/Main/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift index 011e26c..de5f5c0 100644 --- a/Box42/Main/BoxBaseContainerViewController.swift +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -12,7 +12,7 @@ class BoxBaseContainerViewController: NSViewController { var splitView: BoxBaseSplitView = BoxBaseSplitView() var contentGroup: BoxContentsViewGroup = BoxContentsViewGroup() var toolbarGroupVC: ToolbarViewController = ToolbarViewController() - // var quickSlotGroupVC: QuickSlotViewController = QuickSlotViewController() + var quickSlotGroupVC: QuickSlotViewController = QuickSlotViewController() var functionGroupVC: BoxFunctionViewController = BoxFunctionViewController() let windowViewGroupVC: WindowButtonViewController = WindowButtonViewController() var leftContainer: MovableContainerView = MovableContainerView() @@ -76,7 +76,7 @@ class BoxBaseContainerViewController: NSViewController { leftContainer.addSubview(windowViewGroupVC.view) leftContainer.addSubview(buttonGroupVC.view) leftContainer.addSubview(toolbarGroupVC.view) -// leftContainer.addSubview(quickSlotGroupVC.view) + leftContainer.addSubview(quickSlotGroupVC.view) leftContainer.addSubview(functionGroupVC.view) leftContainerAutolayout() @@ -101,15 +101,15 @@ class BoxBaseContainerViewController: NSViewController { make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) make.left.equalTo(leftContainer) - make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) + make.bottom.equalTo(quickSlotGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) } -// quickSlotGroupVC.view.snp.makeConstraints { make in -// make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-27) -// make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) -// make.left.equalTo(leftContainer) -// make.height.equalTo(178) -// } + quickSlotGroupVC.view.snp.makeConstraints { make in + make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-27) + make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) + make.left.equalTo(leftContainer) + make.height.equalTo(178) + } functionGroupVC.view.snp.makeConstraints { make in make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) diff --git a/Box42/QuickSlot/Controller/QuickSlotViewController.swift b/Box42/QuickSlot/Controller/QuickSlotViewController.swift new file mode 100644 index 0000000..898e56b --- /dev/null +++ b/Box42/QuickSlot/Controller/QuickSlotViewController.swift @@ -0,0 +1,40 @@ +// +// QuickSlotViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import AppKit + +class QuickSlotViewController: NSViewController { + var viewModel: QuickSlotViewModel! + + override func loadView() { + super.viewDidLoad() + let quickSlotViewGroup = QuickSlotGroupView() + quickSlotViewGroup.quickslotAction = quickslotAction + + self.view = quickSlotViewGroup + } + + func setupHeader() { + // headerLabel을 뷰에 추가하고 레이아웃을 설정합니다. + } + + func setupGroupView() { + // groupView를 뷰에 추가하고 레이아웃을 설정합니다. + } + + func setupButtons() { + // 4x2 버튼을 groupView에 추가하고 레이아웃을 설정합니다. + } + + @objc func buttonTapped(sender: NSButton) { + // 버튼이 눌렸을 때의 처리 + } + + func quickslotAction() { + print("quick slot") + } +} diff --git a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift new file mode 100644 index 0000000..e5fcf51 --- /dev/null +++ b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift @@ -0,0 +1,14 @@ +// +// QuickSlotButtonModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Foundation + +// Model +struct QuickSlotButtonModel { + let id: UUID + var title: String +} diff --git a/Box42/QuickSlot/Model/QuickSlotUI.swift b/Box42/QuickSlot/Model/QuickSlotUI.swift new file mode 100644 index 0000000..cefdbbf --- /dev/null +++ b/Box42/QuickSlot/Model/QuickSlotUI.swift @@ -0,0 +1,22 @@ +// +// QuickSlotUI.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit + +struct QuickSlotUI { + struct size { + static let font: CGFloat = CGFloat(16).pointsToPixels() + static let headerHeight: CGFloat = 22 + 13 + } + + struct animation { + } + + struct color { + static let pinText = NSColor(hex: "#696969") + } +} diff --git a/Box42/QuickSlot/View/QuickSlotGroupView.swift b/Box42/QuickSlot/View/QuickSlotGroupView.swift new file mode 100644 index 0000000..35497a7 --- /dev/null +++ b/Box42/QuickSlot/View/QuickSlotGroupView.swift @@ -0,0 +1,47 @@ +// +// QuickSlotGroupView.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit +import SnapKit + +class QuickSlotGroupView: NSView { + lazy var divider: NSBox = TopDivider(completion: { self.dividerAction?() }) + lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { self.quickslotAction?() }) + + var dividerAction: (() -> Void)? + var quickslotAction: (() -> Void)? + + override init(frame: NSRect) { + super.init(frame: frame) + setupViews() + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + setupConstraints() + } + + private func setupViews() { + self.addSubview(divider) + self.addSubview(headerView) + } + + private func setupConstraints() { + divider.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.right.equalToSuperview() + } + + headerView.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.right.equalToSuperview() + make.height.equalTo(QuickSlotUI.size.headerHeight) + } + } +} diff --git a/Box42/QuickSlot/View/QuickSlotHeaderView.swift b/Box42/QuickSlot/View/QuickSlotHeaderView.swift new file mode 100644 index 0000000..443ed69 --- /dev/null +++ b/Box42/QuickSlot/View/QuickSlotHeaderView.swift @@ -0,0 +1,55 @@ +// +// QuickSlotHeaderView.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit +import SnapKit + +class QuickSlotHeaderView: NSView { + + private var callback: (() -> Void)? + private var QuickSlotHeaderButton: NSButton! + private var QuickSlotHeaderLabel: NSTextField! + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + QuickSlotHeaderButton = NSButton(image: image, target: self, action: #selector(pin)) + QuickSlotHeaderButton.isBordered = false + QuickSlotHeaderButton.wantsLayer = true + QuickSlotHeaderButton.layer?.backgroundColor = NSColor.clear.cgColor + + self.addSubview(QuickSlotHeaderButton) + + QuickSlotHeaderLabel = NSTextField(labelWithString: "Quick Slot") + QuickSlotHeaderLabel.font = NSFont(name: "Inter", size: QuickSlotUI.size.font) + QuickSlotHeaderLabel.textColor = NSColor(hex: "#696969") + QuickSlotHeaderLabel.backgroundColor = NSColor.clear + QuickSlotHeaderLabel.isBordered = false + + self.addSubview(QuickSlotHeaderLabel) + + QuickSlotHeaderButton.snp.makeConstraints { make in + make.left.equalToSuperview() + make.top.equalToSuperview().offset(13) + } + + QuickSlotHeaderLabel.snp.makeConstraints { make in + make.left.equalTo(QuickSlotHeaderButton.snp.right).offset(4) + make.bottom.equalTo(QuickSlotHeaderButton.snp.bottom) + } + + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func pin() { + callback?() + } +} diff --git a/Box42/FunctionButton/View/TopDivider.swift b/Box42/QuickSlot/View/TopDivider.swift similarity index 100% rename from Box42/FunctionButton/View/TopDivider.swift rename to Box42/QuickSlot/View/TopDivider.swift diff --git a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift new file mode 100644 index 0000000..53c546e --- /dev/null +++ b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift @@ -0,0 +1,29 @@ +// +// QuickSlotViewModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit + +// ViewModel +class QuickSlotViewModel { + var buttons: [QuickSlotButtonModel] = [ + // 초기 버튼 데이터 + ] + + func addButton(_ button: QuickSlotButtonModel) { + buttons.append(button) + } + + func removeButton(id: UUID) { + buttons.removeAll { $0.id == id } + } + + func updateButton(id: UUID, newTitle: String) { + if let index = buttons.firstIndex(where: { $0.id == id }) { + buttons[index].title = newTitle + } + } +} diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift index 205a202..a7a0ff6 100644 --- a/Box42/WebView/URL/URLModel.swift +++ b/Box42/WebView/URL/URLModel.swift @@ -21,14 +21,49 @@ struct URLModel { } } +struct UserDataA: Codable { + var uuid: String + var nickname: String + var theme: Int + var icon: String + var urlList: [_URLModel] + var profileImage: String +} + +struct _URLModel: Codable { + var name: String + var url: String +} + struct URLModels { var info: [URLModel] - + let strData = """ + { + \"uuid\":\"8a8b9d71-3c10-4cbc-8b3a-ae1b5c215f40\", + \"nickname\":\"sechung\", + \"theme\":0, + \"icon\":\"fox\", + \"urlList\":[ + {\"name\":\"home\",\"url\":\"https://42box.kr/\"}, + {\"name\":\"23Coaltheme\",\"url\":\"https://42box.github.io/front-end/\"}, + {\"name\":\"loopback\",\"url\":\"http://127.0.0.1:3000/\"}, + {\"name\":\"Box42\",\"url\":\"https://42box.github.io/front-end/#/box\"}, + {\"name\":\"Intra 42\",\"url\":\"https://intra.42.fr\"}, + {\"name\":\"Jiphyeonjeon\",\"url\":\"https://42library.kr\"}, + {\"name\":\"42STAT\",\"url\":\"https://stat.42seoul.kr/home\"}, + {\"name\":\"24Hane\",\"url\":\"https://24hoursarenotenough.42seoul.kr\"}, + {\"name\":\"80kCoding\",\"url\":\"https://80000coding.oopy.io\"}, + {\"name\":\"where42\",\"url\":\"https://www.where42.kr\"}, + {\"name\":\"cabi\",\"url\":\"https://cabi.42seoul.io/\"}, + {\"name\":\"42gg\",\"url\":\"https://42gg.kr/\"} + ], + \"profileImage\":\"dummy-images.png\" + } + """ // Network logic api call 날려서 받아올 것. let URLstring: [nameUrl] = [ ("home", "https://42box.kr/"), ("23Coaltheme", "https://42box.github.io/front-end/"), - // ("home", "http://127.0.0.1:3000/"), ("Box 42", "https://42box.github.io/front-end/#/box"), ("Intra 42", "https://intra.42.fr"), ("Jiphyeonjeon", "https://42library.kr"), @@ -40,4 +75,33 @@ struct URLModels { ("42gg", "https://42gg.kr/"), ("textart", "https://textart.sh/"), ] + + +// let a = URLModel(name: "name", url: "url") +// var m = URLModels(info: [a]) +// var strData = m.strData +// var dicData : Dictionary = [String: String]() +// do { +// dicData = try JSONSerialization.jsonObject(with: Data(strData.utf8), options: []) as! Dictionary +// } catch { +// print(error.localizedDescription) +// } +// print(dicData["home"]) +// print(dicData) +// +// +// let jsonData = Data(strData.utf8) +// do { +// let userData = try JSONDecoder().decode(UserDataA.self, from: jsonData) +// for urlModel in userData.urlList { +// print(urlModel.name, urlModel.url) +// } +// +// +// if let homeURLModel = userData.urlList.first(where: { $0.name == "home" }) { +// print(homeURLModel.url) +// } +// } catch { +// print(error.localizedDescription) +// } } From f95ec59a3a6728b03dec4e0d230bf9f4c5138420 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sun, 27 Aug 2023 06:02:29 +0900 Subject: [PATCH 27/33] =?UTF-8?q?feat:=20collection=20view=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 4 + Box42/Menubar/MenubarViewController.swift | 2 +- .../View/QuickSlotButtonGridView.swift | 90 +++++++++++++++++++ Box42/QuickSlot/View/QuickSlotGroupView.swift | 20 ++++- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 Box42/QuickSlot/View/QuickSlotButtonGridView.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 7044783..8b1e6ae 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -74,6 +74,7 @@ DE97CA7F2A9A73A9001073DE /* QuickSlotUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */; }; DE97CA862A9A7404001073DE /* QuickSlotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */; }; DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */; }; + DE97CA8A2A9A792F001073DE /* QuickSlotButtonGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */; }; DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */; }; DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */; }; DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */; }; @@ -156,6 +157,7 @@ DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotHeaderView.swift; sourceTree = ""; }; DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotGroupView.swift; sourceTree = ""; }; DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotUI.swift; sourceTree = ""; }; + DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonGridView.swift; sourceTree = ""; }; DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RotateImage+NSImage.swift"; sourceTree = ""; }; DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewController.swift; sourceTree = ""; }; DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowButtonUI.swift; sourceTree = ""; }; @@ -406,6 +408,7 @@ children = ( DE44081C2A928F760091937A /* TopDivider.swift */, DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */, + DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */, DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */, ); path = View; @@ -619,6 +622,7 @@ DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, + DE97CA8A2A9A792F001073DE /* QuickSlotButtonGridView.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index e9b361c..c62e462 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -122,7 +122,7 @@ extension MenubarViewController: MenubarViewControllerDelegate { } window.level = .floating } - boxWindowController?.showWindow(sender) + boxWindowController?.showWindow(sender) } } } diff --git a/Box42/QuickSlot/View/QuickSlotButtonGridView.swift b/Box42/QuickSlot/View/QuickSlotButtonGridView.swift new file mode 100644 index 0000000..a429614 --- /dev/null +++ b/Box42/QuickSlot/View/QuickSlotButtonGridView.swift @@ -0,0 +1,90 @@ +// +// QuickSlotButtonGridView.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Cocoa + +class QuickSlotButtonGridView: NSCollectionView, NSCollectionViewDelegate, NSCollectionViewDataSource { + + private var callback: (() -> Void)? + + init(frame frameRect: NSRect, completion: @escaping () -> Void) { + super.init(frame: frameRect) + self.callback = completion + self.frame = NSRect(x: 0, y: 0, width: 267, height: 134) + + let layout = NSCollectionViewFlowLayout() + let itemSize: CGFloat = 10 + layout.itemSize = NSSize(width: itemSize, height: itemSize) + layout.minimumInteritemSpacing = 10 + layout.minimumLineSpacing = 10 + layout.sectionInset = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + + self.collectionViewLayout = layout + self.delegate = self + self.dataSource = self + + self.register(MyCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyCollectionViewItem")) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int { + return 4 + } + + func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { + let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyCollectionViewItem"), for: indexPath) + let customItem = item as? MyCollectionViewItem + + customItem?.view.wantsLayer = true + customItem?.button.title = "Button \(indexPath.item)" + customItem?.button.target = self + + if indexPath.item % 2 == 0 { + customItem?.view.layer?.backgroundColor = NSColor.red.cgColor + } else { + customItem?.view.layer?.backgroundColor = NSColor.blue.cgColor + } + + print(customItem) + return customItem ?? item + } +} + +class MyCollectionViewItem: NSCollectionViewItem { + var button = NSButton() + var uniqueID: String = UUID().uuidString + + override func awakeFromNib() { + super.awakeFromNib() + print("Unique ID: \(uniqueID)") + } + + override func loadView() { + self.view = NSView() + self.view.addSubview(button) + + self.view.frame = CGRect(x: 0, y: 0, width: 30, height: 30) + + button.snp.makeConstraints { make in + make.top.bottom.left.right.equalToSuperview() + } + } + + override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + print(nibName, nibBundle) + print("MyCollectionViewItem instance created.") + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + print("MyCollectionViewItem instance created.") + } +} diff --git a/Box42/QuickSlot/View/QuickSlotGroupView.swift b/Box42/QuickSlot/View/QuickSlotGroupView.swift index 35497a7..d476ec8 100644 --- a/Box42/QuickSlot/View/QuickSlotGroupView.swift +++ b/Box42/QuickSlot/View/QuickSlotGroupView.swift @@ -9,11 +9,14 @@ import AppKit import SnapKit class QuickSlotGroupView: NSView { - lazy var divider: NSBox = TopDivider(completion: { self.dividerAction?() }) - lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { self.quickslotAction?() }) + lazy var divider: NSBox = TopDivider(completion: { [weak self] in self?.dividerAction?() }) + lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.quickslotAction?() }) + lazy var buttonGridView: QuickSlotButtonGridView = QuickSlotButtonGridView(frame: CGRect(x: 0, y: 0, width: 267, height: 134), completion: { [weak self] in self?.buttonAction?() }) + lazy var footerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.quickslotAction?() }) var dividerAction: (() -> Void)? var quickslotAction: (() -> Void)? + var buttonAction: (() -> Void)? override init(frame: NSRect) { super.init(frame: frame) @@ -30,6 +33,9 @@ class QuickSlotGroupView: NSView { private func setupViews() { self.addSubview(divider) self.addSubview(headerView) + self.addSubview(buttonGridView) + self.addSubview(footerView) + } private func setupConstraints() { @@ -43,5 +49,15 @@ class QuickSlotGroupView: NSView { make.left.right.equalToSuperview() make.height.equalTo(QuickSlotUI.size.headerHeight) } + + buttonGridView.snp.makeConstraints { make in + make.top.equalTo(headerView.snp.bottom).offset(14) + make.left.right.equalToSuperview() + } + + footerView.snp.makeConstraints { make in + make.top.equalTo(buttonGridView.snp.bottom).offset(14) + make.left.right.bottom.equalToSuperview() + } } } From c7b0baebc1a02abb8db3c13b36f6b33598687cff Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:28:26 +0900 Subject: [PATCH 28/33] =?UTF-8?q?refactor(const):=20=EC=83=81=EC=88=98?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20enum=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 52 +++++++++-- Box42/BoxWindowController.swift | 6 +- .../Model/FunctionButtonUI.swift | 8 +- .../PreferencesViewController.swift | 1 - Box42/QuickSlot/Model/QuickSlotUI.swift | 14 +-- .../View/{TopDivider.swift => Divider.swift} | 4 +- .../View/QuickSlotButtonGridView.swift | 90 ------------------- Box42/Shared/Constants.swift | 6 +- Box42/Shared/NotifConst.swift | 16 ++++ Box42/WindowButton/Model/WindowButtonUI.swift | 8 +- 10 files changed, 82 insertions(+), 123 deletions(-) rename Box42/QuickSlot/View/{TopDivider.swift => Divider.swift} (90%) delete mode 100644 Box42/QuickSlot/View/QuickSlotButtonGridView.swift create mode 100644 Box42/Shared/NotifConst.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 8b1e6ae..6ef337a 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -60,10 +60,16 @@ DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408072A9240300091937A /* BoxFunctionButtonView.swift */; }; DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44080B2A924B520091937A /* BoxFunctionViewGroup.swift */; }; DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */; }; - DE44081D2A928F760091937A /* TopDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44081C2A928F760091937A /* TopDivider.swift */; }; + DE44081D2A928F760091937A /* Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44081C2A928F760091937A /* Divider.swift */; }; + DE62BE5A2A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DE62BE582A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib */; }; + DE62BE672A9BA92E00D97E06 /* QuickSlotButtonViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7F9D432A9B7A4700F8ACAE /* QuickSlotButtonViewItem.swift */; }; + DE6332E42A9BB8F800DCFAF6 /* QuickSlotButtonCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE62BE312A9B869900D97E06 /* QuickSlotButtonCollectionViewController.swift */; }; + DE6332E82A9BBEF800DCFAF6 /* NotifConst.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE6332E72A9BBEF800DCFAF6 /* NotifConst.swift */; }; + DE6332F22A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE6332F12A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesViewController.swift */; }; + DE7F9D462A9B7A4700F8ACAE /* QuickSlotButtonViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = DE7F9D442A9B7A4700F8ACAE /* QuickSlotButtonViewItem.xib */; }; DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */; }; DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F532A591F1400FC3B77 /* PreferencesView.swift */; }; DE874F572A591F2500FC3B77 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F562A591F2500FC3B77 /* Icon.swift */; }; @@ -74,7 +80,6 @@ DE97CA7F2A9A73A9001073DE /* QuickSlotUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */; }; DE97CA862A9A7404001073DE /* QuickSlotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */; }; DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */; }; - DE97CA8A2A9A792F001073DE /* QuickSlotButtonGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */; }; DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */; }; DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */; }; DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */; }; @@ -143,10 +148,16 @@ DE4408072A9240300091937A /* BoxFunctionButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionButtonView.swift; sourceTree = ""; }; DE44080B2A924B520091937A /* BoxFunctionViewGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxFunctionViewGroup.swift; sourceTree = ""; }; DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "keyDown+BoxBaseContainerViewController.swift"; path = "Main/keyDown+BoxBaseContainerViewController.swift"; sourceTree = ""; }; - DE44081C2A928F760091937A /* TopDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopDivider.swift; sourceTree = ""; }; + DE44081C2A928F760091937A /* Divider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Divider.swift; sourceTree = ""; }; + DE62BE312A9B869900D97E06 /* QuickSlotButtonCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonCollectionViewController.swift; sourceTree = ""; }; + DE62BE582A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QuickSlotButtonCollectionViewController.xib; sourceTree = ""; }; + DE6332E72A9BBEF800DCFAF6 /* NotifConst.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifConst.swift; sourceTree = ""; }; + DE6332F12A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotScriptsLogicController.swift; sourceTree = ""; }; DE77BA502A82580400713683 /* MenubarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarViewModel.swift; sourceTree = ""; }; DE77BA552A82637900713683 /* StateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateManager.swift; sourceTree = ""; }; DE7A25792A6D8CA20043225A /* PreferencesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; + DE7F9D432A9B7A4700F8ACAE /* QuickSlotButtonViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonViewItem.swift; sourceTree = ""; }; + DE7F9D442A9B7A4700F8ACAE /* QuickSlotButtonViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QuickSlotButtonViewItem.xib; sourceTree = ""; }; DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hotkey.swift; sourceTree = ""; }; DE874F532A591F1400FC3B77 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; DE874F562A591F2500FC3B77 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; @@ -157,7 +168,6 @@ DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotHeaderView.swift; sourceTree = ""; }; DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotGroupView.swift; sourceTree = ""; }; DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotUI.swift; sourceTree = ""; }; - DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonGridView.swift; sourceTree = ""; }; DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RotateImage+NSImage.swift"; sourceTree = ""; }; DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewController.swift; sourceTree = ""; }; DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowButtonUI.swift; sourceTree = ""; }; @@ -370,16 +380,36 @@ path = View; sourceTree = ""; }; + DE62BE632A9BA8CC00D97E06 /* ButtonCollectionView */ = { + isa = PBXGroup; + children = ( + DE62BE312A9B869900D97E06 /* QuickSlotButtonCollectionViewController.swift */, + DE62BE582A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib */, + DE7F9D482A9B7A4E00F8ACAE /* Vertical Item */, + ); + path = ButtonCollectionView; + sourceTree = ""; + }; DE77BA542A82636500713683 /* Shared */ = { isa = PBXGroup; children = ( DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */, DE77BA552A82637900713683 /* StateManager.swift */, DE0A91622A8E6A5400D1D6F1 /* Constants.swift */, + DE6332E72A9BBEF800DCFAF6 /* NotifConst.swift */, ); path = Shared; sourceTree = ""; }; + DE7F9D482A9B7A4E00F8ACAE /* Vertical Item */ = { + isa = PBXGroup; + children = ( + DE7F9D432A9B7A4700F8ACAE /* QuickSlotButtonViewItem.swift */, + DE7F9D442A9B7A4700F8ACAE /* QuickSlotButtonViewItem.xib */, + ); + path = "Vertical Item"; + sourceTree = ""; + }; DE874F512A591EC600FC3B77 /* Preferences */ = { isa = PBXGroup; children = ( @@ -406,10 +436,10 @@ DE98E8412A98DDEB00F8744A /* View */ = { isa = PBXGroup; children = ( - DE44081C2A928F760091937A /* TopDivider.swift */, + DE44081C2A928F760091937A /* Divider.swift */, DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */, - DE97CA892A9A792F001073DE /* QuickSlotButtonGridView.swift */, DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */, + DE62BE632A9BA8CC00D97E06 /* ButtonCollectionView */, ); path = View; sourceTree = ""; @@ -484,6 +514,7 @@ isa = PBXGroup; children = ( DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */, + DE6332F12A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift */, ); path = Controller; sourceTree = ""; @@ -578,7 +609,9 @@ DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */, DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */, DEB862D42A85124500278FCD /* cleanCache.sh in Resources */, + DE7F9D462A9B7A4700F8ACAE /* QuickSlotButtonViewItem.xib in Resources */, DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */, + DE62BE5A2A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib in Resources */, DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -594,6 +627,7 @@ DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */, DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, + DE62BE672A9BA92E00D97E06 /* QuickSlotButtonViewItem.swift in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, @@ -609,8 +643,10 @@ DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */, DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */, DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */, + DE6332E82A9BBEF800DCFAF6 /* NotifConst.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, + DE6332E42A9BB8F800DCFAF6 /* QuickSlotButtonCollectionViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */, DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */, @@ -619,10 +655,10 @@ DE0A91862A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */, + DE6332F22A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, - DE97CA8A2A9A792F001073DE /* QuickSlotButtonGridView.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, @@ -651,7 +687,7 @@ DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, - DE44081D2A928F760091937A /* TopDivider.swift in Sources */, + DE44081D2A928F760091937A /* Divider.swift in Sources */, DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, diff --git a/Box42/BoxWindowController.swift b/Box42/BoxWindowController.swift index fe74981..8acc892 100644 --- a/Box42/BoxWindowController.swift +++ b/Box42/BoxWindowController.swift @@ -18,16 +18,12 @@ class BoxWindowController: NSWindowController, NSWindowDelegate { windowInstance.title = "Box" windowInstance.titlebarAppearsTransparent = true windowInstance.titleVisibility = .hidden - windowInstance.isReleasedWhenClosed = false windowInstance.isMovableByWindowBackground = true + windowInstance.isReleasedWhenClosed = false windowInstance.standardWindowButton(.closeButton)?.isHidden = true windowInstance.standardWindowButton(.miniaturizeButton)?.isHidden = true windowInstance.standardWindowButton(.zoomButton)?.isHidden = true - if let zoomButton = windowInstance.standardWindowButton(.zoomButton) { - zoomButton.isHidden = true - } - let boxViewController = BoxBaseContainerViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController } diff --git a/Box42/FunctionButton/Model/FunctionButtonUI.swift b/Box42/FunctionButton/Model/FunctionButtonUI.swift index e5c9522..096fa6b 100644 --- a/Box42/FunctionButton/Model/FunctionButtonUI.swift +++ b/Box42/FunctionButton/Model/FunctionButtonUI.swift @@ -7,17 +7,17 @@ import AppKit -struct FunctionButtonUI { - struct size { +enum FunctionButtonUI { + enum size { static let font: CGFloat = 14 static let pinWidth: CGFloat = 89 static let pinHeight: CGFloat = 27 } - struct animation { + enum animation { } - struct color { + enum color { static let pinText = NSColor(hex: "#696969") } } diff --git a/Box42/Preferences/PreferencesViewController.swift b/Box42/Preferences/PreferencesViewController.swift index 6604203..5a6c36d 100644 --- a/Box42/Preferences/PreferencesViewController.swift +++ b/Box42/Preferences/PreferencesViewController.swift @@ -141,7 +141,6 @@ class PreferencesViewController: NSViewController { print("Error: \(error)") } } - } } diff --git a/Box42/QuickSlot/Model/QuickSlotUI.swift b/Box42/QuickSlot/Model/QuickSlotUI.swift index cefdbbf..c61c2cf 100644 --- a/Box42/QuickSlot/Model/QuickSlotUI.swift +++ b/Box42/QuickSlot/Model/QuickSlotUI.swift @@ -7,16 +7,18 @@ import AppKit -struct QuickSlotUI { - struct size { +enum QuickSlotUI { + enum size { static let font: CGFloat = CGFloat(16).pointsToPixels() - static let headerHeight: CGFloat = 22 + 13 + static let headerHeight: CGFloat = 35 + static let button: CGFloat = 59 + static let lineSpacing: CGFloat = 12 } - struct animation { + enum animation { } - struct color { - static let pinText = NSColor(hex: "#696969") + enum color { +// static let pinText = NSColor(hex: "#696969") } } diff --git a/Box42/QuickSlot/View/TopDivider.swift b/Box42/QuickSlot/View/Divider.swift similarity index 90% rename from Box42/QuickSlot/View/TopDivider.swift rename to Box42/QuickSlot/View/Divider.swift index 81a39de..a3dfdb0 100644 --- a/Box42/QuickSlot/View/TopDivider.swift +++ b/Box42/QuickSlot/View/Divider.swift @@ -1,5 +1,5 @@ // -// TopDivider.swift +// Divider.swift // Box42 // // Created by Chanhee Kim on 8/21/23. @@ -7,7 +7,7 @@ import AppKit -class TopDivider: NSBox { +class Divider: NSBox { private var callback: (() -> Void)? diff --git a/Box42/QuickSlot/View/QuickSlotButtonGridView.swift b/Box42/QuickSlot/View/QuickSlotButtonGridView.swift deleted file mode 100644 index a429614..0000000 --- a/Box42/QuickSlot/View/QuickSlotButtonGridView.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// QuickSlotButtonGridView.swift -// Box42 -// -// Created by Chanhee Kim on 8/27/23. -// - -import Cocoa - -class QuickSlotButtonGridView: NSCollectionView, NSCollectionViewDelegate, NSCollectionViewDataSource { - - private var callback: (() -> Void)? - - init(frame frameRect: NSRect, completion: @escaping () -> Void) { - super.init(frame: frameRect) - self.callback = completion - self.frame = NSRect(x: 0, y: 0, width: 267, height: 134) - - let layout = NSCollectionViewFlowLayout() - let itemSize: CGFloat = 10 - layout.itemSize = NSSize(width: itemSize, height: itemSize) - layout.minimumInteritemSpacing = 10 - layout.minimumLineSpacing = 10 - layout.sectionInset = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - - self.collectionViewLayout = layout - self.delegate = self - self.dataSource = self - - self.register(MyCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyCollectionViewItem")) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int { - return 4 - } - - func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { - let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyCollectionViewItem"), for: indexPath) - let customItem = item as? MyCollectionViewItem - - customItem?.view.wantsLayer = true - customItem?.button.title = "Button \(indexPath.item)" - customItem?.button.target = self - - if indexPath.item % 2 == 0 { - customItem?.view.layer?.backgroundColor = NSColor.red.cgColor - } else { - customItem?.view.layer?.backgroundColor = NSColor.blue.cgColor - } - - print(customItem) - return customItem ?? item - } -} - -class MyCollectionViewItem: NSCollectionViewItem { - var button = NSButton() - var uniqueID: String = UUID().uuidString - - override func awakeFromNib() { - super.awakeFromNib() - print("Unique ID: \(uniqueID)") - } - - override func loadView() { - self.view = NSView() - self.view.addSubview(button) - - self.view.frame = CGRect(x: 0, y: 0, width: 30, height: 30) - - button.snp.makeConstraints { make in - make.top.bottom.left.right.equalToSuperview() - } - } - - override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - print(nibName, nibBundle) - print("MyCollectionViewItem instance created.") - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - print("MyCollectionViewItem instance created.") - } -} diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift index 5e6347d..e0af4fc 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -5,14 +5,14 @@ // Created by Chanhee Kim on 8/17/23. // -struct Constants { - struct url { +enum Constants { + enum url { static let initialName = "home" // static let initialPage = "https://42box.kr" static let initialPage = "https://profile.intra.42.fr/" } - struct UI { + enum UI { static let groupAutolayout = 16 static let topWindow = 64 - 16 static let leadingWindow = 14 diff --git a/Box42/Shared/NotifConst.swift b/Box42/Shared/NotifConst.swift new file mode 100644 index 0000000..fb42e6a --- /dev/null +++ b/Box42/Shared/NotifConst.swift @@ -0,0 +1,16 @@ +// +// ConstantsNotificationCenter.swift +// Box42 +// +// Created by Chanhee Kim on 8/28/23. +// + +enum NotifConst { // NotificationCenter Constants + enum object { + static let collectionButtonTapped = "collectionButtonTapped" + } + + enum userInfo { + + } +} diff --git a/Box42/WindowButton/Model/WindowButtonUI.swift b/Box42/WindowButton/Model/WindowButtonUI.swift index a9e3bdc..66252be 100644 --- a/Box42/WindowButton/Model/WindowButtonUI.swift +++ b/Box42/WindowButton/Model/WindowButtonUI.swift @@ -7,18 +7,18 @@ import AppKit -struct WindowButtonUI { - struct size { +enum WindowButtonUI { + enum size { static let diameter = 15 static let cornerRadius = CGFloat(diameter / 2) static let offset = 8 } - struct animation { + enum animation { static let duration = TimeInterval(0.2) } - struct color { + enum color { static let maximize = NSColor(hex: "#76DF7A").cgColor static let minimize = NSColor(hex: "#FFCE51").cgColor static let close = NSColor(hex: "#F36161").cgColor From 3206686cd14f24b3cbe44cd5d7cd62c75a139fdf Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:29:14 +0900 Subject: [PATCH 29/33] =?UTF-8?q?style:=20=F0=9F=A6=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Menubar/MenubarViewModel.swift | 1 + .../42pack_icon/sitting_fox/Contents.json | 6 +++++ .../sitting_fox0.imageset/Contents.json | 21 ++++++++++++++++++ .../sitting_fox0.imageset/sitting_fox0.png | Bin 0 -> 3816 bytes .../sitting_fox1.imageset/Contents.json | 21 ++++++++++++++++++ .../sitting_fox1.imageset/sitting_fox1.png | Bin 0 -> 3673 bytes .../sitting_fox2.imageset/Contents.json | 21 ++++++++++++++++++ .../sitting_fox2.imageset/sitting_fox2.png | Bin 0 -> 3765 bytes .../sitting_fox3.imageset/Contents.json | 21 ++++++++++++++++++ .../sitting_fox3.imageset/sitting_fox3.png | Bin 0 -> 3673 bytes 10 files changed, 91 insertions(+) create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/sitting_fox0.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/sitting_fox1.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/sitting_fox2.png create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/sitting_fox3.png diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index b1daf88..9946f07 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -32,6 +32,7 @@ class StatusBarViewModel { case "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "lee_\(i)"))} case "box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(i)"))} case "fox": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "fox_page\(i)"))} + case "sitting_fox": for i in (0...3) {statusBar.frames.append(NSImage(imageLiteralResourceName: "sitting_fox\(i)"))} case "box_oc": for i in (1...2) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_oc\(i)"))} default : for i in (1...11) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42flip_0\(i)"))} } diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/Contents.json new file mode 100644 index 0000000..44e39c0 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sitting_fox0.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/sitting_fox0.png b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/sitting_fox0.png new file mode 100644 index 0000000000000000000000000000000000000000..61410e0272cc73b2503e760d0a37ef62831d9dc8 GIT binary patch literal 3816 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600Z<%L_t(oh27X&h}2~m$MMg* zr!tc;gXln%bg;0ZuA&R+rXW!yq3|lgpscH)6G0Fm1riZfU}a?nEiv5^WXo@?9T4a!q5+fng9EL56|~KJkRq^iU|K#rDkv`rTI7> z5kHUFIHi8vi&^+2BKA&;m6OycxRlajtj0NbHzJ;B**K*e@k8`WE-#0CX$d`PhruMbQ^{AR>OL)Vm%Z;fkW@S1gQ( zohhZBh^S4g(zrIfmL<>uf!%)>Bh=$8T4 zVh|7GnMz+ru>@PX0gUEw=V1$ODvE08DSrQse{hNHaLTITO}rctyQa(FiKrP|!uwb@ z$v&UO>-Z}oPE5_bsi_%Uuj~OIZKHi4Ret}5{rE%P!uw8xA#8-tK9RaMuJ&(tYUZJ{%`D>3t4TN&|8xawV?8Tp4s87U1j- z7~e{#<*?BsZ~wYyZsn!lj)?oKg)QMY6ZbBa4?5XfF2Ls|=XlytO=D~JV`fo4R!rT8 zYpWSiJ8<=m`s7(#iua~u{@6NzHP|Ds+Pc!aR$loiZmH(9W5SK7*vMY)!iI_4+_u(5 z#PVXy+wiH;Njf7ze~O5!s}&{!*CU^~Wpc>qREAR44lIv|ZN+5Xj*m4wbgMJBDI%7P zvU!4VvoRlw1by9ZoCp5fZJ>lLI5qpa92IOEqcO27(@N`71s=jC& zZdAiOvmH@6%}Oct;bQq_GS;=LzAd-ok$PS_!p1JSG@nsQ=?2_^7g|&adBuCNOFpA7 zHtlOV;i{|KP9mIAS}FglR*j>>a_ZGzyc?8n{jDaUyH+lx^pt!_F6XyZ_kT+Eplc%H z%Q5@w7PyqsOnfFM33Uz2ac{eP=i4e@jSfV_(71he3ml}BuEK?~2RtTcDTn2o!l{Y= e7ur>Doz{QBJhs#^hiQHQ0000f6 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600U)7L_t(oh3(i)Xk1ko#_``t z()a;d+6q!Fq9RyI#Sd_!(4}HYkQS7#R1~zjwdztt5L}h&My(4K)QuGsEuvthy3r~K zw)oY6wlRLRQjIN1Y%;Hlb0@vMxk)FJnUY8!xMc3hIp;qAdCz;^b09&cP`y!#%hN??uGHuDEPdGvHE6gV=!!@mfSYKI`C=uE*EK?Mo5yP)ey6jaURr zq7H5|b``fru{9!g%@~+c54PdiqUlrIjo)Fh!mY$XtSFj3#Dfv>bEV&Pcn4P%O^2~D zBKD`0dLp9HRp%{eHn=aHG7T?aM?`#A^jU|UxTVzR4-7=azLZj0tdU!V&#)F#XkeKP zxD&&81W#7xI*vQBXEA_L54Rk9aAVQbKu_`cH~fRkzer(6XmA;ectF$$N%8+IKi}A|eF&SP0Gt{bSw4X~aFcw}FRS^G{tlY2 zQxw;Ha{7C0iimH^jdi8qO5BHyGGuT2J{P2^;@OSjDns|0nFjlDdqj*h8*1O@Af?nV zC-XIOf?r)sx)vL7eg{E1rOz=K5l5HND(IoAhpvz+5~WoHy$$p!uWh}fG_S{)I;PJ5mw+zPD6pnMGD)Y($$zOOJ; z_XSMI1$bQE1)F0=@NPu>P5j7iiwCgS?jsoGitF+JECsA+_nw3 r6x3C?YIM)`&kyG!w^VfwZmH@&e9C*&3(olA00000NkvXXu0mjfEj9Gi literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/Contents.json new file mode 100644 index 0000000..dd0f044 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sitting_fox2.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/sitting_fox2.png b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/sitting_fox2.png new file mode 100644 index 0000000000000000000000000000000000000000..050be9b79d32377a2957abfa9f1a4277602f9a6b GIT binary patch literal 3765 zcmV;m4odNfP)f6 zXi@@54ZTQ_E-Enz5K6$103tR-RB%L5k){YTDBysjLy@r}iiH7DvFijGMAUI`6dRUF zWUU$Bym{}eS9UO(Z2>7`&z9wUXbV-Il#&6`Y8GKGQ04S2&F6MJnWNa;Ck|;8QE#r9r;7G||@X{|> z%+C|c55>;RS}qbKr-&IQTvLXPlM{>K&(BTgi^a?^4mXV>;xX8n8Ce|RasXz}{8imI52H3ZN4bfe_i~WlJ|C&UW9+{8AKoW!}eExnGFE2re(F+`iE_46#!l9 z0Z_aBhs|Iw0E)7{bq;-T9=d#9QpDmcXDh4R++0fmpKB>E=%LdZt9g$j;($`3&Zthxi`{{&gM}5&R^+h%b~yM9Zd3AWW9ETgVfL z1(`yIK=_}U_z%PWq}jQaiQ4!P(3V&Nr6C$XejWfQDiI(Fdt@un?|lo#M+5oIi_w{w zo%_#%{(V=tO#a9gB!7-$M?^BX5>d|Vn*3S!?g~$*UQipUPL&zMmg;!4Do9IA%up=Rh? z=qPj=x&RGBx1dpI68aT-2O}^EromdU5o`ssU{5#*j)WJ%$?!5bA1;Eoz?EiTr=n?cd`V|I)p<|3Oju?MT93~aB0<#&j8`F+Cg&D?-VWzQItUA^l>xvD zRIYI4MQ`g1<+DyrL=EogS06Xii({| zv`U^zjmmKqDIK93(F5q|^fLNk`gQs{RV`IdRle#b)i%{Ds;|}NsClUI)k@Ub)kf6b zsWa4l)YH_rsduU0(?DsMX@qO!YV6TCtMPOWZH~(v?wpc2hv(eZgf-1HBQ#fN?$aF5 zoYvCT^3%%Fs?s{6^;Da#?V+8jy+iwi_M{F~$4y6|vqR^k&SQoO!;_KDsATjprgSxR z{dFa}^}2()GkV5)QF?`X?Rxk03HmJkB>f%wz4}uIItC#I1qQ7Kw+-=zEW;GTU55RJ zuZ@h2VvIHzbs0S}Rx=JT&Npr~zH34@aW`3J(qMAU6l2OVO*7qXdf5y%vo}jIt1%lg zhs_<#1?IcWhb_<+P8LFo28$a^64R5J!)#@aTGB0pEekEXET35!SjAgyv+B3{Xl-wu zZrx~o$A)4PXj5p@WAm%6nJw40#`fA=@?77!tLJvleQsxN$G6*KchjC~A7a13zSsVP zgQJ7Uq0M2^(ZDg$vDWbhi^d9LZDyT!LOXdmt#&%*^w!zIS?qk+`4<X~g?%56 z2@eae34a)26HyS+zks@6$%2*zuOhu7%OdYYnM6sVdZQJi6QY}=U&naIl*dS8tzuWk zUW(I*6U24LW8oFzvR(TOpM zEs5_rp_~TJ^wNN(wM(bCZ0;`Z6P^ce2XB(^$}i_nB)KM)Cp}7bP2Qe7nc|*Ok@8f) z7E}wKr~0SXrM^xJP1~RLDLp2=Jp-4Km~m7{5vB?IGPN`FGKaIwvx>8%%bb_(Ts9>N z5;bK**^9Ef#WdN^)PTf9vR*Qp{o-l7 zTcBI8wqSIn=gRt3(5j`YdRObOE?Pal#&6AmwS={4Ykw%TE-Wv6xh`g1Pmxy9nxe7w ze(PI{6^cd0H#WFzsN0CzDA+i-Y3`<~O&?2mB^OJrODjs>Z{}{k_?699m0x|@lC)*8 z%%N=0R?Jr6*6Z8cw;d=~F3&F?+a9vLa|dHb$&Qyhm+ZVyVOLSNi?B>BD~Ee(8aT1AWbo&CM;EEoH56tE6@EV8X%6-*|u1-NtOIZ>P7H z9s-9XhaP{M`0e$>L5F*fu#U8SXZT%h2eqT56Y5;vIn|ZYCGC#u9zGg)w718lr{jCe z@An_mJyvsE<#^c%!il02pHAkVoIaIx>gnm^(__6$dheWxJ#(!uyl?Pq(Ao3ne9xWf z_v}A;-u3*k3(gmgUSwVDy5w-FbHIL};|Kd6ItCpEJBJ*Hx-UCj?irppeBz4xmD5+f zub#UWaP88_{E^}7QP*$YNVp-r$-DXJR{E{yw{vdK+*xxMeYfPE(!GlNn)e%iH2tw% z>L5Kn>ODH}V8MesW8ASPKV|>)e!S=*`C-L`&P4Mg+egPHeJ3wJUif(YN!F8@r^P=j z|6Kdbc>FRj6+1QlT=e|YubW?}zu5oM?q%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600Y5EL_t(oh3(f{h*nh;2k_sX z87I4%+Djx+(Z$S&q8=*nO(Ii5q3|g}u*|p83WDfr5IvOj(8Zt|-7JeBA|g^M3A#W~ zL6}jRSn61LDMy=`)x$ocr|*6~9l`JqhwnT4tiAU7@3q(3Yo&KTUZ07Gn^Q`?7>SBUBBhiH zdq!Hw^tAe3C*OeFJgh2S2e2q2R@F^RsRv8(a53}=uE!SWl-#JnDWy|z8TyOoBpie7 zSc_jHVmPJL8xh0ZlADC}m{<&bfSV#>Lyg>pcn4<|L%(2FM0{I$hf_Kk_hJDCkkWxyWY+f^RUzUu9r?5OCzAt2^VFj)z$!x{!i1?z@#Y=0B$6dI)jp#Z# z#y{_t++=);sTjrx#>oU%U=tSOo*G@daV=I?jkjXmNmz*6Fd4l~M8Cnzh}hCrX9IE* zuo@Q^LnHDLf#0wTr^yMYj1fGG$0Opqb_>@Tk`u~!T#Bc0eiP9VEQyH6+UjgTF5wl- zuWDd{`wHX!h={?elT%84cpI}@h`kpP*R<8ufLyPf0he@OOUS`r{=XR;u}wb0Kg$_( z06S&R@5T=N84>@KV>G37JYK@w7VG{H5$9GSS9q--kK&dZ*&*~bAy+0@#y&awm4EjX z?ZMC_Rd4*G_Hlt(o^aLCAOOGPxLd(}9H629ck+bJuPn~mq?JEj)3#_yF&qp`p` zv`QAca8*Qn)=p9FvAh#k;}W^jFJriP`m0)75v}5R5D!MgvQ88=x(d#~jhH2qY*r~8 zZv2j=5%FB76B_n&kW%WGGuGKS4`<0lr(%X&O&l)l#DYfMNh>rZ$Nqb7ihKc+v*irD zue-$4EuM^s#Z@PDLT)sX^vSU>4=;CPVHemSw?Zo;;_u4cMyIl+>SZoo?ZVJbu}5xB zSIa%zR}rzd8%0&f^~fD6EPignFTkZkMVa!#bP0om(8!LxO|#P&0H*?nuCxlB@OZSb3=F`bRx? fgyJZf6 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600U)7L_t(oh3(i)Xk1ko#_``t z()a;d+6q!Fq9RyI#Sd_!(4}HYkQS7#R1~zjwdztt5L}h&My(4K)QuGsEuvthy3r~K zw)oY6wlRLRQjIN1Y%;Hlb0@vMxk)FJnUY8!xMc3hIp;qAdCz;^b09&cP`y!#%hN??uGHuDEPdGvHE6gV=!!@mfSYKI`C=uE*EK?Mo5yP)ey6jaURr zq7H5|b``fru{9!g%@~+c54PdiqUlrIjo)Fh!mY$XtSFj3#Dfv>bEV&Pcn4P%O^2~D zBKD`0dLp9HRp%{eHn=aHG7T?aM?`#A^jU|UxTVzR4-7=azLZj0tdU!V&#)F#XkeKP zxD&&81W#7xI*vQBXEA_L54Rk9aAVQbKu_`cH~fRkzer(6XmA;ectF$$N%8+IKi}A|eF&SP0Gt{bSw4X~aFcw}FRS^G{tlY2 zQxw;Ha{7C0iimH^jdi8qO5BHyGGuT2J{P2^;@OSjDns|0nFjlDdqj*h8*1O@Af?nV zC-XIOf?r)sx)vL7eg{E1rOz=K5l5HND(IoAhpvz+5~WoHy$$p!uWh}fG_S{)I;PJ5mw+zPD6pnMGD)Y($$zOOJ; z_XSMI1$bQE1)F0=@NPu>P5j7iiwCgS?jsoGitF+JECsA+_nw3 r6x3C?YIM)`&kyG!w^VfwZmH@&e9C*&3(olA00000NkvXXu0mjfEj9Gi literal 0 HcmV?d00001 From 9cb68a38065ace1c1330e708a20d19fd870786db Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:30:22 +0900 Subject: [PATCH 30/33] =?UTF-8?q?feat(collectionView):=20xib=EB=A1=9C=20co?= =?UTF-8?q?llection=20view=EB=A5=BC=20=EC=A7=84=ED=96=89=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ckSlotButtonCollectionViewController.swift | 110 ++++++++++++++++++ ...uickSlotButtonCollectionViewController.xib | 57 +++++++++ .../QuickSlotButtonViewItem.swift | 14 +++ .../Vertical Item/QuickSlotButtonViewItem.xib | 23 ++++ 4 files changed, 204 insertions(+) create mode 100644 Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift create mode 100644 Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib create mode 100644 Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.swift create mode 100644 Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.xib diff --git a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift new file mode 100644 index 0000000..edfaf7f --- /dev/null +++ b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift @@ -0,0 +1,110 @@ +// +// QuickSlotButtonCollectionViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Cocoa +import Combine + +class QuickSlotButtonCollectionViewController: NSViewController { + @IBOutlet weak var quickSlotButtonCollectionView: NSCollectionView! + var viewModel: QuickSlotViewModel = QuickSlotViewModel() + var cancellables: Set = [] + + override func viewDidLoad() { + super.viewDidLoad() + initializeCombine() + + quickSlotButtonCollectionView.delegate = self + quickSlotButtonCollectionView.dataSource = self + + quickSlotButtonCollectionView.register(NSNib(nibNamed: NSNib.Name("QuickSlotButtonViewItem"), bundle: nil), forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "QuickSlotButtonViewItem")) + + initializeView() + } + + override func viewDidLayout() { + super.viewDidLayout() + constraintsView() + } + + override func awakeFromNib() { + super.awakeFromNib() + } + + init() { + super.init(nibName: "QuickSlotButtonCollectionViewController", bundle: nil) + } + + func initializeCombine() { + viewModel.$buttons + .sink { [weak self] _ in + self?.quickSlotButtonCollectionView.reloadData() + } + .store(in: &cancellables) + } + + func initializeView() { + // MARK: - Setup FlowLayout View + let flowLayout: NSCollectionViewFlowLayout = NSCollectionViewFlowLayout() + flowLayout.itemSize = CGSize(width: QuickSlotUI.size.button, height: QuickSlotUI.size.button) + flowLayout.scrollDirection = .horizontal + flowLayout.minimumLineSpacing = QuickSlotUI.size.lineSpacing + flowLayout.sectionInset = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + quickSlotButtonCollectionView.collectionViewLayout = flowLayout + + // MARK: - Setup Collection View + quickSlotButtonCollectionView.wantsLayer = true + quickSlotButtonCollectionView.layer?.borderWidth = 0 + quickSlotButtonCollectionView.layer?.borderColor = NSColor.clear.cgColor + quickSlotButtonCollectionView.backgroundColors = [NSColor.clear] + + if let scrollView = quickSlotButtonCollectionView.enclosingScrollView { +// scrollView.hasVerticalScroller = false +// scrollView.hasHorizontalScroller = false + scrollView.backgroundColor = NSColor.clear + scrollView.drawsBackground = false + } + } + + func constraintsView() { + quickSlotButtonCollectionView.frame = self.view.bounds + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } +} + +extension QuickSlotButtonCollectionViewController: NSCollectionViewDelegate, NSCollectionViewDataSource { + + func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int { + return viewModel.buttons.count + } + + func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { + let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "QuickSlotButtonViewItem"), for: indexPath) + + if let customItem = item as? QuickSlotButtonViewItem { + let buttonModel = viewModel.buttons[indexPath.item] + let btn = NSButton() +// btn.title = "\(indexPath)" + btn.title = buttonModel.title + btn.action = #selector(collectionButtonTapped) + btn.target = self + btn.wantsLayer = true + btn.layer?.backgroundColor = NSColor.red.cgColor + customItem.view.addSubview(btn) + btn.frame = CGRect(x: 0, y: 0, width: QuickSlotUI.size.button, height: QuickSlotUI.size.button) + } + return item + } +} + +extension QuickSlotButtonCollectionViewController { + @objc func collectionButtonTapped(_ sender: NSButton) { + NotificationCenter.default.post(name: NSNotification.Name(NotifConst.object.collectionButtonTapped), object: sender) + } +} diff --git a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib new file mode 100644 index 0000000..0fda14b --- /dev/null +++ b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.swift b/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.swift new file mode 100644 index 0000000..b3cc217 --- /dev/null +++ b/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.swift @@ -0,0 +1,14 @@ +// +// QuickSlotButtonViewItem.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Cocoa + +class QuickSlotButtonViewItem: NSCollectionViewItem { + override func viewDidLoad() { + super.viewDidLoad() + } +} diff --git a/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.xib b/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.xib new file mode 100644 index 0000000..346e9c3 --- /dev/null +++ b/Box42/QuickSlot/View/ButtonCollectionView/Vertical Item/QuickSlotButtonViewItem.xib @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + From 172d06f42d8d5b1a07b6120abdad1f9500e82f16 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:31:51 +0900 Subject: [PATCH 31/33] =?UTF-8?q?feat:=20NotificationCenter=EB=A1=9C=20Qui?= =?UTF-8?q?ckSlot=EC=9D=98=20Button=20Action=EC=9D=84=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuickSlotScriptsLogicController.swift | 57 +++++ .../Controller/QuickSlotViewController.swift | 30 +-- Box42/Resources/AppDelegate.swift | 238 +++++++++--------- 3 files changed, 188 insertions(+), 137 deletions(-) create mode 100644 Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift diff --git a/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift b/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift new file mode 100644 index 0000000..1038e76 --- /dev/null +++ b/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift @@ -0,0 +1,57 @@ +// +// QuickSlotScriptsLogicController.swift +// Box42 +// +// Created by Chanhee Kim on 8/28/23. +// + +import AppKit + +class ScriptsLogicController { + + static let shared = ScriptsLogicController() + + private init() { + NotificationCenter.default.addObserver(self, selector: #selector(handleButtonTapped), name: NSNotification.Name(NotifConst.object.collectionButtonTapped), object: nil) + } + + @objc func handleButtonTapped(notification: NSNotification) { + if let button = notification.object as? NSButton { + let buttonTitle = button.title // 메인 스레드에서 타이틀을 캡쳐 + print("Button with title \(buttonTitle) was tapped") + + DispatchQueue.global(qos: .background).async { [weak self] in + if buttonTitle == "clean" { + self?.executeCleanScript() + } + } + } + } + + private func executeCleanScript() { + if let scriptPath = Bundle.main.path(forResource: "cleanCache", ofType: "sh") { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = [scriptPath] + + let outputPipe = Pipe() + task.standardOutput = outputPipe + task.standardError = outputPipe + + task.launch() + task.waitUntilExit() + + let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: outputData, encoding: .utf8) ?? "" + + DispatchQueue.main.async { + print("Output: \(output)") + } + } else { + DispatchQueue.main.async { + print("Script not found") + } + } + } + +} diff --git a/Box42/QuickSlot/Controller/QuickSlotViewController.swift b/Box42/QuickSlot/Controller/QuickSlotViewController.swift index 898e56b..177b5f9 100644 --- a/Box42/QuickSlot/Controller/QuickSlotViewController.swift +++ b/Box42/QuickSlot/Controller/QuickSlotViewController.swift @@ -9,32 +9,24 @@ import AppKit class QuickSlotViewController: NSViewController { var viewModel: QuickSlotViewModel! + var buttonCollectionView: QuickSlotButtonCollectionViewController! override func loadView() { - super.viewDidLoad() let quickSlotViewGroup = QuickSlotGroupView() - quickSlotViewGroup.quickslotAction = quickslotAction + quickSlotViewGroup.headerAction = headerAction + NotificationCenter.default.addObserver(self, selector: #selector(handleButtonTapped), name: NSNotification.Name(NotifConst.object.collectionButtonTapped), object: nil) + self.view = quickSlotViewGroup } - func setupHeader() { - // headerLabel을 뷰에 추가하고 레이아웃을 설정합니다. + func headerAction() { + print("quick slot header") } - - func setupGroupView() { - // groupView를 뷰에 추가하고 레이아웃을 설정합니다. - } - - func setupButtons() { - // 4x2 버튼을 groupView에 추가하고 레이아웃을 설정합니다. - } - - @objc func buttonTapped(sender: NSButton) { - // 버튼이 눌렸을 때의 처리 - } - - func quickslotAction() { - print("quick slot") + + @objc func handleButtonTapped(notification: NSNotification) { + if let button = notification.object as? NSButton { + print("Button with title \(button.title) was tapped") + } } } diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 9bde3d6..65fb651 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -9,125 +9,127 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { - var menubarController = MenubarViewController() + var menubarController = MenubarViewController() lazy var storage = Storage() - - func applicationWillFinishLaunching(_ notification: Notification) { - menubarController.menubarViewControllerInit() - } - - func applicationDidFinishLaunching(_ aNotification: Notification) { - menubarController.menubarViewControllerStart() -// alertAccessibility() -// hotkey() - -// storage.storageTimerEvent() + + func applicationWillFinishLaunching(_ notification: Notification) { + menubarController.menubarViewControllerInit() } - - func applicationWillTerminate(_ aNotification: Notification) { - // Insert code here to tear down your application - } - - func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } - - // MARK: - Core Data stack - - lazy var persistentContainer: NSPersistentContainer = { - /* - The persistent container for the application. This implementation - creates and returns a container, having loaded the store for the - application to it. This property is optional since there are legitimate - error conditions that could cause the creation of the store to fail. - */ - let container = NSPersistentContainer(name: "Box42") - container.loadPersistentStores(completionHandler: { (storeDescription, error) in - if let error = error { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - - /* - Typical reasons for an error here include: - * The parent directory does not exist, cannot be created, or disallows writing. - * The persistent store is not accessible, due to permissions or data protection when the device is locked. - * The device is out of space. - * The store could not be migrated to the current model version. - Check the error message to determine what the actual problem was. - */ - fatalError("Unresolved error \(error)") - } - }) - return container - }() - - // MARK: - Core Data Saving and Undo support - - @IBAction func saveAction(_ sender: AnyObject?) { - // Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user. - let context = persistentContainer.viewContext - - if !context.commitEditing() { - NSLog("\(NSStringFromClass(type(of: self))) unable to commit editing before saving") - } - if context.hasChanges { - do { - try context.save() - } catch { - // Customize this code block to include application-specific recovery steps. - let nserror = error as NSError - NSApplication.shared.presentError(nserror) - } - } - } - - func windowWillReturnUndoManager(window: NSWindow) -> UndoManager? { - // Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application. - return persistentContainer.viewContext.undoManager - } - - func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { - // Save changes in the application's managed object context before the application terminates. - let context = persistentContainer.viewContext - - if !context.commitEditing() { - NSLog("\(NSStringFromClass(type(of: self))) unable to commit editing to terminate") - return .terminateCancel - } - - if !context.hasChanges { - return .terminateNow - } - - do { - try context.save() - } catch { - let nserror = error as NSError - - // Customize this code block to include application-specific recovery steps. - let result = sender.presentError(nserror) - if (result) { - return .terminateCancel - } - - let question = NSLocalizedString("Could not save changes while quitting. Quit anyway?", comment: "Quit without saves error question message") - let info = NSLocalizedString("Quitting now will lose any changes you have made since the last successful save", comment: "Quit without saves error question info"); - let quitButton = NSLocalizedString("Quit anyway", comment: "Quit anyway button title") - let cancelButton = NSLocalizedString("Cancel", comment: "Cancel button title") - let alert = NSAlert() - alert.messageText = question - alert.informativeText = info - alert.addButton(withTitle: quitButton) - alert.addButton(withTitle: cancelButton) - - let answer = alert.runModal() - if answer == .alertSecondButtonReturn { - return .terminateCancel - } - } - // If we got here, it is time to quit. - return .terminateNow - } - + + func applicationDidFinishLaunching(_ aNotification: Notification) { + menubarController.menubarViewControllerStart() + // alertAccessibility() + // hotkey() + + // storage.storageTimerEvent() + _ = ScriptsLogicController.shared + + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } + + // MARK: - Core Data stack + + lazy var persistentContainer: NSPersistentContainer = { + /* + The persistent container for the application. This implementation + creates and returns a container, having loaded the store for the + application to it. This property is optional since there are legitimate + error conditions that could cause the creation of the store to fail. + */ + let container = NSPersistentContainer(name: "Box42") + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + + /* + Typical reasons for an error here include: + * The parent directory does not exist, cannot be created, or disallows writing. + * The persistent store is not accessible, due to permissions or data protection when the device is locked. + * The device is out of space. + * The store could not be migrated to the current model version. + Check the error message to determine what the actual problem was. + */ + fatalError("Unresolved error \(error)") + } + }) + return container + }() + + // MARK: - Core Data Saving and Undo support + + @IBAction func saveAction(_ sender: AnyObject?) { + // Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user. + let context = persistentContainer.viewContext + + if !context.commitEditing() { + NSLog("\(NSStringFromClass(type(of: self))) unable to commit editing before saving") + } + if context.hasChanges { + do { + try context.save() + } catch { + // Customize this code block to include application-specific recovery steps. + let nserror = error as NSError + NSApplication.shared.presentError(nserror) + } + } + } + + func windowWillReturnUndoManager(window: NSWindow) -> UndoManager? { + // Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application. + return persistentContainer.viewContext.undoManager + } + + func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { + // Save changes in the application's managed object context before the application terminates. + let context = persistentContainer.viewContext + + if !context.commitEditing() { + NSLog("\(NSStringFromClass(type(of: self))) unable to commit editing to terminate") + return .terminateCancel + } + + if !context.hasChanges { + return .terminateNow + } + + do { + try context.save() + } catch { + let nserror = error as NSError + + // Customize this code block to include application-specific recovery steps. + let result = sender.presentError(nserror) + if (result) { + return .terminateCancel + } + + let question = NSLocalizedString("Could not save changes while quitting. Quit anyway?", comment: "Quit without saves error question message") + let info = NSLocalizedString("Quitting now will lose any changes you have made since the last successful save", comment: "Quit without saves error question info"); + let quitButton = NSLocalizedString("Quit anyway", comment: "Quit anyway button title") + let cancelButton = NSLocalizedString("Cancel", comment: "Cancel button title") + let alert = NSAlert() + alert.messageText = question + alert.informativeText = info + alert.addButton(withTitle: quitButton) + alert.addButton(withTitle: cancelButton) + + let answer = alert.runModal() + if answer == .alertSecondButtonReturn { + return .terminateCancel + } + } + // If we got here, it is time to quit. + return .terminateNow + } + } From e4b9a7560f6c296b09f8bc21b4bb221daf1a2fa4 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:32:23 +0900 Subject: [PATCH 32/33] =?UTF-8?q?feat:=20QuickSlotGroup=EC=9D=98=20?= =?UTF-8?q?=EB=B7=B0=EB=A5=BC=20=EA=B5=AC=EC=84=B1=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/QuickSlot/View/QuickSlotGroupView.swift | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Box42/QuickSlot/View/QuickSlotGroupView.swift b/Box42/QuickSlot/View/QuickSlotGroupView.swift index d476ec8..228c26b 100644 --- a/Box42/QuickSlot/View/QuickSlotGroupView.swift +++ b/Box42/QuickSlot/View/QuickSlotGroupView.swift @@ -9,14 +9,13 @@ import AppKit import SnapKit class QuickSlotGroupView: NSView { - lazy var divider: NSBox = TopDivider(completion: { [weak self] in self?.dividerAction?() }) - lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.quickslotAction?() }) - lazy var buttonGridView: QuickSlotButtonGridView = QuickSlotButtonGridView(frame: CGRect(x: 0, y: 0, width: 267, height: 134), completion: { [weak self] in self?.buttonAction?() }) - lazy var footerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.quickslotAction?() }) + + lazy var divider: NSBox = Divider(completion: { [weak self] in self?.dividerAction?() }) + lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.headerAction?() }) + lazy var buttonCollectionView: QuickSlotButtonCollectionViewController = QuickSlotButtonCollectionViewController() var dividerAction: (() -> Void)? - var quickslotAction: (() -> Void)? - var buttonAction: (() -> Void)? + var headerAction: (() -> Void)? override init(frame: NSRect) { super.init(frame: frame) @@ -33,8 +32,7 @@ class QuickSlotGroupView: NSView { private func setupViews() { self.addSubview(divider) self.addSubview(headerView) - self.addSubview(buttonGridView) - self.addSubview(footerView) + self.addSubview(buttonCollectionView.view) } @@ -50,13 +48,8 @@ class QuickSlotGroupView: NSView { make.height.equalTo(QuickSlotUI.size.headerHeight) } - buttonGridView.snp.makeConstraints { make in + buttonCollectionView.view.snp.makeConstraints { make in make.top.equalTo(headerView.snp.bottom).offset(14) - make.left.right.equalToSuperview() - } - - footerView.snp.makeConstraints { make in - make.top.equalTo(buttonGridView.snp.bottom).offset(14) make.left.right.bottom.equalToSuperview() } } From 466ed6cde0fde2978e61b102597a80874f39e108 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 28 Aug 2023 03:32:52 +0900 Subject: [PATCH 33/33] =?UTF-8?q?feat(mvvm):=20quick=20slot=20view?= =?UTF-8?q?=EC=99=80=20view=20model=EC=9D=84=20mvvm=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=EC=84=B1=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/QuickSlot/Model/QuickSlotButtonModel.swift | 5 +++++ Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift index e5fcf51..8049fc7 100644 --- a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift +++ b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift @@ -11,4 +11,9 @@ import Foundation struct QuickSlotButtonModel { let id: UUID var title: String + + init(title: String = "Default") { + self.id = UUID() + self.title = title + } } diff --git a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift index 53c546e..fe3e1da 100644 --- a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift +++ b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift @@ -6,13 +6,19 @@ // import AppKit +import Combine -// ViewModel class QuickSlotViewModel { - var buttons: [QuickSlotButtonModel] = [ - // 초기 버튼 데이터 - ] + @Published var buttons: [QuickSlotButtonModel] = [] + init() { + let button1 = QuickSlotButtonModel(title: "clean") + let button2 = QuickSlotButtonModel(title: "icons") + let button3 = QuickSlotButtonModel(title: "scripts") + + buttons = [button1, button2, button3] + } + func addButton(_ button: QuickSlotButtonModel) { buttons.append(button) }