diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 54be299..6ef337a 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,25 +46,49 @@ 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 */; }; + 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 */; }; 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 */; }; - DE44081D2A928F760091937A /* TopDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44081C2A928F760091937A /* TopDivider.swift */; }; + DE4408152A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.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 */; }; 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 */; }; + 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 */; }; + 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 */ @@ -100,10 +123,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,25 +134,49 @@ 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 = ""; }; + 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 = ""; }; 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 = ""; }; - DE44081C2A928F760091937A /* TopDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopDivider.swift; sourceTree = ""; }; + DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "keyDown+BoxBaseContainerViewController.swift"; path = "Main/keyDown+BoxBaseContainerViewController.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 = ""; }; 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 = ""; }; + 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 = ""; }; + 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 */ @@ -167,20 +213,20 @@ DE018BB12A5099F900FF0AA3 /* Box42 */ = { isa = PBXGroup; children = ( - DE0A916B2A8E7DC700D1D6F1 /* UI */, - DE1F1A202A8B50CA00A88DD8 /* Main */, + DE77BA542A82636500713683 /* Shared */, DEF749302A85655E00D987C8 /* Extensions */, - DEB862E82A853F6800278FCD /* Window */, + DE018C0E2A509C0C00FF0AA3 /* Menubar */, + DE9DA8122A97F1E2001C0D3B /* ButtonGroup */, + DE1F1A202A8B50CA00A88DD8 /* Main */, DEB862D22A8511D600278FCD /* Scripts */, - DE77BA542A82636500713683 /* Shared */, DE874F512A591EC600FC3B77 /* Preferences */, DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, + DEB862E82A853F6800278FCD /* WindowButton */, DE0A917D2A8F864300D1D6F1 /* Toolbar */, + DE98E8382A98D48700F8744A /* QuickSlot */, DE4407F82A923E5B0091937A /* FunctionButton */, - DE1F1A182A8B50BB00A88DD8 /* Box */, - DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; sourceTree = ""; @@ -263,6 +309,7 @@ children = ( DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */, DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */, + DE3FF3A22A97D2A6009C88EF /* DisplayURLTextfield.swift */, DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */, DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */, DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */, @@ -279,27 +326,33 @@ name = Frameworks; sourceTree = ""; }; - DE1F1A182A8B50BB00A88DD8 /* Box */ = { + DE1F1A202A8B50CA00A88DD8 /* Main */ = { isa = PBXGroup; children = ( + DE0A916B2A8E7DC700D1D6F1 /* UI */, DE4408202A9297EE0091937A /* View */, DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, + DE4408142A92750D0091937A /* keyDown+BoxBaseContainerViewController.swift */, + DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, ); - name = Box; + name = Main; sourceTree = ""; }; - DE1F1A202A8B50CA00A88DD8 /* Main */ = { + DE3FF36F2A978A6E009C88EF /* View */ = { isa = PBXGroup; children = ( - DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */, - DE4408142A92750D0091937A /* keyDown+BoxViewController.swift */, + DE3FF3722A978AB8009C88EF /* WindowCloseButton.swift */, + DE3FF3732A978AB8009C88EF /* WindowMinimizeButton.swift */, + DE3FF3702A978AB8009C88EF /* WindowMaximizeButton.swift */, + DE3FF3712A978AB8009C88EF /* WindowViewGroup.swift */, ); - name = Main; + path = View; sourceTree = ""; }; DE4407F82A923E5B0091937A /* FunctionButton */ = { isa = PBXGroup; children = ( + DEE0FA942A9A553A00085A65 /* Model */, DE4407FC2A923E920091937A /* View */, DE4407F92A923E860091937A /* BoxFunctionViewController.swift */, ); @@ -309,7 +362,6 @@ DE4407FC2A923E920091937A /* View */ = { isa = PBXGroup; children = ( - DE44081C2A928F760091937A /* TopDivider.swift */, DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */, DE4408012A923EB60091937A /* PinButtonView.swift */, DE4408042A923EC00091937A /* QuitButtonView.swift */, @@ -322,12 +374,20 @@ DE4408202A9297EE0091937A /* View */ = { isa = PBXGroup; children = ( - DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); - name = View; - path = Box/View; + path = View; + sourceTree = ""; + }; + DE62BE632A9BA8CC00D97E06 /* ButtonCollectionView */ = { + isa = PBXGroup; + children = ( + DE62BE312A9B869900D97E06 /* QuickSlotButtonCollectionViewController.swift */, + DE62BE582A9BA31700D97E06 /* QuickSlotButtonCollectionViewController.xib */, + DE7F9D482A9B7A4E00F8ACAE /* Vertical Item */, + ); + path = ButtonCollectionView; sourceTree = ""; }; DE77BA542A82636500713683 /* Shared */ = { @@ -336,10 +396,20 @@ 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 = ( @@ -352,6 +422,62 @@ path = Preferences; sourceTree = ""; }; + DE98E8382A98D48700F8744A /* QuickSlot */ = { + isa = PBXGroup; + children = ( + DE98E84E2A98E04F00F8744A /* ViewModel */, + DE98E8492A98E02400F8744A /* Model */, + DE98E8412A98DDEB00F8744A /* View */, + DEE0FA872A9A022100085A65 /* Controller */, + ); + path = QuickSlot; + sourceTree = ""; + }; + DE98E8412A98DDEB00F8744A /* View */ = { + isa = PBXGroup; + children = ( + DE44081C2A928F760091937A /* Divider.swift */, + DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */, + DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */, + DE62BE632A9BA8CC00D97E06 /* ButtonCollectionView */, + ); + path = View; + sourceTree = ""; + }; + DE98E8492A98E02400F8744A /* Model */ = { + isa = PBXGroup; + children = ( + DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */, + DE97CA7E2A9A73A9001073DE /* QuickSlotUI.swift */, + ); + path = Model; + sourceTree = ""; + }; + DE98E84E2A98E04F00F8744A /* ViewModel */ = { + isa = PBXGroup; + children = ( + DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + DE98E8532A98EA4F00F8744A /* Model */ = { + isa = PBXGroup; + children = ( + DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */, + ); + path = Model; + sourceTree = ""; + }; + DE9DA8122A97F1E2001C0D3B /* ButtonGroup */ = { + isa = PBXGroup; + children = ( + DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, + DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */, + ); + path = ButtonGroup; + sourceTree = ""; + }; DEB862D22A8511D600278FCD /* Scripts */ = { isa = PBXGroup; children = ( @@ -374,21 +500,43 @@ path = sh; sourceTree = ""; }; - DEB862E82A853F6800278FCD /* Window */ = { + DEB862E82A853F6800278FCD /* WindowButton */ = { isa = PBXGroup; children = ( - DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, + DE98E8532A98EA4F00F8744A /* Model */, + DE3FF36F2A978A6E009C88EF /* View */, + DE3FF3692A978A57009C88EF /* WindowButtonViewController.swift */, + ); + path = WindowButton; + sourceTree = ""; + }; + DEE0FA872A9A022100085A65 /* Controller */ = { + isa = PBXGroup; + children = ( + DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */, + DE6332F12A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + DEE0FA942A9A553A00085A65 /* Model */ = { + isa = PBXGroup; + children = ( + DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */, ); - path = Window; + path = Model; sourceTree = ""; }; DEF749302A85655E00D987C8 /* Extensions */ = { isa = PBXGroup; children = ( + DE3FF3662A978A37009C88EF /* HexValue+NSColor.swift */, DE874F5E2A5935CC00FC3B77 /* String.swift */, DEF749312A85657600D987C8 /* NSScreen.swift */, DE1F1A302A8BD68F00A88DD8 /* Double.swift */, DE24E63A2A8FE93900E29F5D /* NSImage.swift */, + DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */, + DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */, ); path = Extensions; sourceTree = ""; @@ -461,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; @@ -473,44 +623,63 @@ 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 */, + DE62BE672A9BA92E00D97E06 /* QuickSlotButtonViewItem.swift 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 */, + 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 */, 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 */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, 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 */, DE018BF32A509B3300FF0AA3 /* MenubarModel.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 */, - DE4408152A92750D0091937A /* keyDown+BoxViewController.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 */, DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */, DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */, DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, 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 */, @@ -518,10 +687,12 @@ 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 */, 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/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift deleted file mode 100644 index 538078f..0000000 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// BoxBaseContainerViewController.swift -// Box42 -// -// Created by Chan on 2023/03/17. -// - -import Cocoa -import SnapKit - -class BoxBaseContainerViewController: NSViewController { - var splitView: BoxBaseSplitView! = BoxBaseSplitView() - var contentGroup: BoxContentsViewGroup! = BoxContentsViewGroup() - var toolbarGroup: BoxToolbarViewGroup! = BoxToolbarViewGroup() - var functionGroupVC: BoxFunctionViewController! = BoxFunctionViewController() - var buttonGroup: BoxButtonViewGroup! - var leftContainer: MovableContainerView! - - override func loadView() { - self.view = NSView() - 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 - } - - 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) - } - print("Triple Click") - } else if clickCount < 2 { - contentGroup.removeAllSubviews() - contentGroup.showWebviews(sender) - } - } - - private func leftContainerInit() { - leftContainer = MovableContainerView() - leftContainer.addSubview(buttonGroup) - leftContainer.addSubview(toolbarGroup) - leftContainer.addSubview(functionGroupVC.view) - leftContainerAutolayout() - leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width - } - - private func leftContainerAutolayout() { - toolbarGroup.snp.makeConstraints { make in - make.top.equalTo(leftContainer).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.right.equalTo(leftContainer).offset(-Constants.UI.GroupAutolayout) - make.left.equalTo(leftContainer) - } - - 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) - } - } - - func viewInit() { - self.boxViewSizeInit() - - splitView.addArrangedSubview(leftContainer) - splitView.addArrangedSubview(contentGroup) - 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) - } - } - - func boxViewSizeInit() { - self.view.frame.size.width = BoxSizeManager.shared.size.width - self.view.frame.size.height = BoxSizeManager.shared.size.height - } -} - -extension BoxBaseContainerViewController: NSSplitViewDelegate { - func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { - - if dividerIndex == 0 { - return 132 - } - return proposedMinimumPosition - } - - func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { - if dividerIndex == 0 { - return 200 - } - return proposedMaximumPosition - } - - func splitView(_ splitView: NSSplitView, resizeSubviewsWithOldSize oldSize: NSSize) { - let dividerThickness = splitView.dividerThickness - let newWidth = splitView.frame.width - dividerThickness - - let leftWidth = leftContainer.frame.width - let contentWidth = newWidth - leftWidth - - leftContainer.frame = NSRect(x: 0, y: 0, width: leftWidth, height: splitView.bounds.height) - contentGroup.frame = NSRect(x: leftWidth + dividerThickness, y: 0, width: contentWidth, height: splitView.bounds.height) - } -} diff --git a/Box42/Box/View/BoxButtonViewGroup.swift b/Box42/Box/View/BoxButtonViewGroup.swift deleted file mode 100644 index 44a2299..0000000 --- a/Box42/Box/View/BoxButtonViewGroup.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// BoxButtonView.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa -import SnapKit - -class BoxButtonViewGroup: NSView { - var boxVM: WebViewModel! = WebViewModel() - var pinSwitch : NSSwitch = NSSwitch() - var clickAction: ((NSButton) -> Void)? - var lastAddedButton: NSView? - var loginInfo: NSView? - - init(clickAction: @escaping (NSButton) -> Void) { - self.clickAction = clickAction - super.init(frame: BoxSizeManager.shared.buttonGroupSizeNSRect) - setupButtons() - } - - 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 - } -} diff --git a/Box42/BoxWindowController.swift b/Box42/BoxWindowController.swift new file mode 100644 index 0000000..8acc892 --- /dev/null +++ b/Box42/BoxWindowController.swift @@ -0,0 +1,44 @@ +// +// 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] + 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.isMovableByWindowBackground = true + windowInstance.isReleasedWhenClosed = false + windowInstance.standardWindowButton(.closeButton)?.isHidden = true + windowInstance.standardWindowButton(.miniaturizeButton)?.isHidden = true + windowInstance.standardWindowButton(.zoomButton)?.isHidden = 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 + } +} 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) + } +} diff --git a/Box42/Extensions/HexValue+NSColor.swift b/Box42/Extensions/HexValue+NSColor.swift new file mode 100644 index 0000000..8360c15 --- /dev/null +++ b/Box42/Extensions/HexValue+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/Extensions/NSScreen.swift b/Box42/Extensions/NSScreen.swift index 778e4fd..836bb71 100644 --- a/Box42/Extensions/NSScreen.swift +++ b/Box42/Extensions/NSScreen.swift @@ -8,9 +8,20 @@ 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 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 { + return CGSize(width: left.width + right.width, height: left.height) } 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/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/FunctionButton/Model/FunctionButtonUI.swift b/Box42/FunctionButton/Model/FunctionButtonUI.swift new file mode 100644 index 0000000..096fa6b --- /dev/null +++ b/Box42/FunctionButton/Model/FunctionButtonUI.swift @@ -0,0 +1,23 @@ +// +// FunctionButtonUI.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit + +enum FunctionButtonUI { + enum size { + static let font: CGFloat = 14 + static let pinWidth: CGFloat = 89 + static let pinHeight: CGFloat = 27 + } + + enum animation { + } + + enum color { + static let pinText = NSColor(hex: "#696969") + } +} 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/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift index 9e5fa88..2e961a0 100644 --- a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -9,11 +9,10 @@ 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-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?() }) var preferenceAction: (() -> Void)? var pinAction: (() -> Void)? @@ -38,38 +37,33 @@ class BoxFunctionViewGroup: NSView { self.addSubview(pinButton) self.addSubview(quitButton) self.addSubview(boxButton) - self.addSubview(divider) } private func setupConstraints() { - divider.snp.makeConstraints { make in + pinButton.snp.makeConstraints { make in make.top.equalToSuperview() - make.left.right.equalToSuperview() - } - - preferenceButton.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) + make.width.equalTo(FunctionButtonUI.size.pinWidth) + make.height.equalTo(FunctionButtonUI.size.pinHeight) } - 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 a91036b..684e3be 100644 --- a/Box42/FunctionButton/View/PinButtonView.swift +++ b/Box42/FunctionButton/View/PinButtonView.swift @@ -6,18 +6,42 @@ // 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.bezelStyle = .texturedRounded - self.target = self - self.action = #selector(pin) + 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: 14) + pinBoxLabel.textColor = NSColor(hex: "#696969") + pinBoxLabel.backgroundColor = NSColor.clear + pinBoxLabel.isBordered = false + + self.addSubview(pinBoxLabel) + + pinBoxButton.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerY.equalToSuperview() + } + + pinBoxLabel.snp.makeConstraints { make in + make.left.equalTo(pinBoxButton.snp.right).offset(2) + make.centerY.equalToSuperview() + } + 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 diff --git a/Box42/Main/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift new file mode 100644 index 0000000..de5f5c0 --- /dev/null +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -0,0 +1,173 @@ +// +// BoxBaseContainerViewController.swift +// Box42 +// +// Created by Chan on 2023/03/17. +// + +import Cocoa +import SnapKit + +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() + var buttonGroupVC: ButtonGroupViewController = ButtonGroupViewController() + weak var menubarVCDelegate: MenubarViewControllerDelegate? // extension + + override func loadView() { + self.view = NSView() + 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 + self.view.layer?.backgroundColor = NSColor(hex: "#E7E7E7").cgColor + } + + func BoxButtonViewGroupInit() -> BoxButtonViewGroup { + + let buttonGroup = BoxButtonViewGroup { sender in + self.clickBtn(sender: sender) + } + + return buttonGroup + } + + 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") + } + } + } + } + + 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(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) + } + + toolbarGroupVC.view.snp.makeConstraints { make in + make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) + make.right.equalTo(leftContainer) + make.left.equalTo(leftContainer) + make.height.equalTo(44 + 14 + 24) + } + + 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(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) + } + + functionGroupVC.view.snp.makeConstraints { make in + make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) + make.left.bottom.equalTo(leftContainer) + } + } + + func viewInit() { + self.boxViewSizeInit() + + splitView.addArrangedSubview(leftContainer) + splitView.addArrangedSubview(contentGroup) + self.view.addSubview(splitView) + + splitView.snp.makeConstraints { make in + 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) + } + } + + func boxViewSizeInit() { + self.view.frame.size.width = BoxSizeManager.shared.size.width + self.view.frame.size.height = BoxSizeManager.shared.size.height + } +} + +extension BoxBaseContainerViewController: NSSplitViewDelegate { + func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { + + if dividerIndex == 0 { + return CGFloat(132).pointsToPixels() + } + return proposedMinimumPosition + } + + func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { + if dividerIndex == 0 { + return CGFloat(312).pointsToPixels() + } + return proposedMaximumPosition + } + + func splitView(_ splitView: NSSplitView, resizeSubviewsWithOldSize oldSize: NSSize) { + let dividerThickness = splitView.dividerThickness + let newWidth = splitView.frame.width - dividerThickness + + let leftWidth = leftContainer.frame.width + let contentWidth = newWidth - leftWidth + + leftContainer.frame = NSRect(x: 0, y: 0, width: leftWidth, height: splitView.bounds.height) + contentGroup.frame = NSRect(x: leftWidth + dividerThickness, y: 0, width: contentWidth, height: splitView.bounds.height) + } +} + +extension BoxBaseContainerViewController: BoxFunctionViewControllerDelegate { + func didTapBoxButton() { + clickBtn(sender: "box") + } +} diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift deleted file mode 100644 index a9692c8..0000000 --- a/Box42/Main/BoxViewController.swift +++ /dev/null @@ -1,63 +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 - 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) - } - - @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.setToggleIsPin() - 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..c62e462 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() @@ -21,7 +21,7 @@ class MenubarViewController: NSWorkspace { func menubarViewControllerStart() { self.menubarStartRunning() self.buttonActionInit() - self.popoverCoentViewInit() + self.popoverContentViewInit() self.startEventMonitoring() } @@ -42,7 +42,7 @@ class MenubarViewController: NSWorkspace { } func buttonInit() { - buttonImageChange("Cat") + buttonImageChange("fox") statusBarVM.statusButtonAppear() } @@ -55,15 +55,15 @@ class MenubarViewController: NSWorkspace { statusBarVM.statusBar.statusItem.button?.target = self } - func popoverCoentViewInit() { - let boxViewController = BoxViewController(nibName: nil, bundle: nil) + func popoverContentViewInit() { + 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,19 +113,18 @@ 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 } - boxWindowController?.showWindow(sender) + boxWindowController?.showWindow(sender) } } - } protocol MenubarViewControllerDelegate: AnyObject { diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index 7a7fb9e..9946f07 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -25,12 +25,14 @@ 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 "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/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/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 new file mode 100644 index 0000000..177b5f9 --- /dev/null +++ b/Box42/QuickSlot/Controller/QuickSlotViewController.swift @@ -0,0 +1,32 @@ +// +// QuickSlotViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/25/23. +// + +import AppKit + +class QuickSlotViewController: NSViewController { + var viewModel: QuickSlotViewModel! + var buttonCollectionView: QuickSlotButtonCollectionViewController! + + override func loadView() { + let quickSlotViewGroup = QuickSlotGroupView() + quickSlotViewGroup.headerAction = headerAction + + NotificationCenter.default.addObserver(self, selector: #selector(handleButtonTapped), name: NSNotification.Name(NotifConst.object.collectionButtonTapped), object: nil) + + self.view = quickSlotViewGroup + } + + func headerAction() { + print("quick slot header") + } + + @objc func handleButtonTapped(notification: NSNotification) { + if let button = notification.object as? NSButton { + print("Button with title \(button.title) was tapped") + } + } +} diff --git a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift new file mode 100644 index 0000000..8049fc7 --- /dev/null +++ b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift @@ -0,0 +1,19 @@ +// +// QuickSlotButtonModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import Foundation + +// Model +struct QuickSlotButtonModel { + let id: UUID + var title: String + + init(title: String = "Default") { + self.id = UUID() + self.title = title + } +} diff --git a/Box42/QuickSlot/Model/QuickSlotUI.swift b/Box42/QuickSlot/Model/QuickSlotUI.swift new file mode 100644 index 0000000..c61c2cf --- /dev/null +++ b/Box42/QuickSlot/Model/QuickSlotUI.swift @@ -0,0 +1,24 @@ +// +// QuickSlotUI.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit + +enum QuickSlotUI { + enum size { + static let font: CGFloat = CGFloat(16).pointsToPixels() + static let headerHeight: CGFloat = 35 + static let button: CGFloat = 59 + static let lineSpacing: CGFloat = 12 + } + + enum animation { + } + + enum color { +// static let pinText = NSColor(hex: "#696969") + } +} 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 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Box42/FunctionButton/View/TopDivider.swift b/Box42/QuickSlot/View/Divider.swift similarity index 90% rename from Box42/FunctionButton/View/TopDivider.swift rename to Box42/QuickSlot/View/Divider.swift index 81a39de..a3dfdb0 100644 --- a/Box42/FunctionButton/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/QuickSlotGroupView.swift b/Box42/QuickSlot/View/QuickSlotGroupView.swift new file mode 100644 index 0000000..228c26b --- /dev/null +++ b/Box42/QuickSlot/View/QuickSlotGroupView.swift @@ -0,0 +1,56 @@ +// +// QuickSlotGroupView.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit +import SnapKit + +class QuickSlotGroupView: NSView { + + 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 headerAction: (() -> 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) + self.addSubview(buttonCollectionView.view) + + } + + 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) + } + + buttonCollectionView.view.snp.makeConstraints { make in + make.top.equalTo(headerView.snp.bottom).offset(14) + make.left.right.bottom.equalToSuperview() + } + } +} 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/QuickSlot/ViewModel/QuickSlotViewModel.swift b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift new file mode 100644 index 0000000..fe3e1da --- /dev/null +++ b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift @@ -0,0 +1,35 @@ +// +// QuickSlotViewModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/27/23. +// + +import AppKit +import Combine + +class QuickSlotViewModel { + @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) + } + + 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/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 26df5dd..65fb651 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -9,124 +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 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 applicationWillFinishLaunching(_ notification: Notification) { + menubarController.menubarViewControllerInit() + } + + 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 + } + } 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 0000000..0892874 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page0.imageset/fox0.png differ diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/Contents.json new file mode 100644 index 0000000..b59bbbf --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "fox1.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_page1.imageset/fox1.png b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/fox1.png new file mode 100644 index 0000000..14ede17 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page1.imageset/fox1.png differ diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/Contents.json new file mode 100644 index 0000000..7b2f55b --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "fox2.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_page2.imageset/fox2.png b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/fox2.png new file mode 100644 index 0000000..2120ecd Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page2.imageset/fox2.png differ 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 0000000..e15e2be Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page3.imageset/fox3.png differ 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 0000000..352f185 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/fox/fox_page4.imageset/fox4.png differ 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 0000000..61410e0 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox0.imageset/sitting_fox0.png differ diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/Contents.json new file mode 100644 index 0000000..1dfc5aa --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sitting_fox1.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_fox1.imageset/sitting_fox1.png b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/sitting_fox1.png new file mode 100644 index 0000000..4ea17f8 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox1.imageset/sitting_fox1.png differ 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 0000000..050be9b Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox2.imageset/sitting_fox2.png differ diff --git a/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/Contents.json new file mode 100644 index 0000000..a64ac22 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sitting_fox3.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_fox3.imageset/sitting_fox3.png b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/sitting_fox3.png new file mode 100644 index 0000000..4ea17f8 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/42pack_icon/sitting_fox/sitting_fox3.imageset/sitting_fox3.png differ diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/_arrow.left.imageset/Contents.json similarity index 100% rename from Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/Icons/_arrow.left.imageset/Contents.json diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/arrow.left@2x.png b/Box42/Resources/Assets.xcassets/Icons/_arrow.left.imageset/arrow.left@2x.png similarity index 100% rename from Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/arrow.left@2x.png rename to Box42/Resources/Assets.xcassets/Icons/_arrow.left.imageset/arrow.left@2x.png 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 0000000..fa00ba0 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Bookmark icon.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Contents.json new file mode 100644 index 0000000..f843e5b --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/Bookmark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Bookmark icon.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} 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 0000000..dcfda9c Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/Star.imageset/Star 3.png differ 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 0000000..8a82ffc Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/arrow-left.imageset/arrow-left.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/Contents.json new file mode 100644 index 0000000..4941e41 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "arrow-right.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/arrow-right.png b/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/arrow-right.png new file mode 100644 index 0000000..73ce0d2 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/arrow-right.imageset/arrow-right.png differ 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 0000000..f035028 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/circle.imageset/Ellipse 1.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Contents.json new file mode 100644 index 0000000..7146232 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.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-box-ver.imageset/Pin icon.png b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Pin icon.png new file mode 100644 index 0000000..f9bd8d6 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/pin-box-ver.imageset/Pin icon.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Contents.json new file mode 100644 index 0000000..966e93e --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.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-box.imageset/Pin icon_45.png b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Pin icon_45.png new file mode 100644 index 0000000..265a579 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/pin-box.imageset/Pin icon_45.png differ 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 0000000..662594e Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/rotate-right.imageset/rotate-right.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/Contents.json new file mode 100644 index 0000000..c71abfa --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "toggle-off.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/toggle-off.png b/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/toggle-off.png new file mode 100644 index 0000000..01634fd Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/toggle-off.imageset/toggle-off.png differ diff --git a/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/Contents.json b/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/Contents.json new file mode 100644 index 0000000..44dd8e0 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "toggle-on.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/toggle-on.png b/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/toggle-on.png new file mode 100644 index 0000000..f47e732 Binary files /dev/null and b/Box42/Resources/Assets.xcassets/uibuttons/toggle-on.imageset/toggle-on.png differ 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 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..e0af4fc 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -5,13 +5,16 @@ // Created by Chanhee Kim on 8/17/23. // -struct Constants { - struct url { - static let InitialName = "home" - static let InitialPage = "https://42box.github.io/front-end/" +enum Constants { + enum url { + static let initialName = "home" +// static let initialPage = "https://42box.kr" + static let initialPage = "https://profile.intra.42.fr/" } - struct UI { - static let GroupAutolayout = 12 + 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/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/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/Toolbar/ToolbarViewController.swift b/Box42/Toolbar/ToolbarViewController.swift index ea32aab..c5df281 100644 --- a/Box42/Toolbar/ToolbarViewController.swift +++ b/Box42/Toolbar/ToolbarViewController.swift @@ -8,24 +8,16 @@ 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) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + let toolbarViewGroup = BoxToolbarViewGroup() + + toolbarViewGroup.sidebar = sidebar + toolbarViewGroup.goBack = goBack + toolbarViewGroup.goFoward = goFoward + toolbarViewGroup.reloadPage = reloadPage + toolbarViewGroup.goToHome = goToHome + + self.view = toolbarViewGroup } override func viewDidLoad() { diff --git a/Box42/Toolbar/View/BoxToolbarViewGroup.swift b/Box42/Toolbar/View/BoxToolbarViewGroup.swift index ac17e8c..00628df 100644 --- a/Box42/Toolbar/View/BoxToolbarViewGroup.swift +++ b/Box42/Toolbar/View/BoxToolbarViewGroup.swift @@ -9,23 +9,73 @@ import AppKit import SnapKit class BoxToolbarViewGroup: NSView { - var toolbarVC: ToolbarViewController? + 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?() }) - 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(goBackButton) + self.addSubview(goForwardButton) + self.addSubview(reloadPageButton) + self.addSubview(sidebarLeading) + self.addSubview(displayURL) +// self.addSubview(goHomePageViaButton) + } + + private func setupConstraints() { + goBackButton.snp.makeConstraints { make in + 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(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(goBackButton) + make.left.equalTo(goForwardButton.snp.right).offset(14) + make.width.equalTo(24) + make.height.equalTo(24) + } - self.wantsLayer = true -// self.addSubview(toolbarVC!.view) + sidebarLeading.snp.makeConstraints { make in + make.top.equalToSuperview() + make.right.equalToSuperview() + make.width.equalTo(24) + make.height.equalTo(24) + } - toolbarVC?.view.translatesAutoresizingMaskIntoConstraints = false - toolbarVC?.view.snp.makeConstraints { make in - make.edges.equalTo(self) + displayURL.snp.makeConstraints { make in + make.top.equalTo(goBackButton.snp.bottom).offset(14) + make.left.right.equalToSuperview() + make.height.equalTo(44) } } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } } 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) { 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/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/BoxContentsViewGroup.swift b/Box42/View/BoxContentsViewGroup.swift similarity index 97% rename from Box42/Box/View/BoxContentsViewGroup.swift rename to Box42/View/BoxContentsViewGroup.swift index 215d0ce..1eb1ee5 100644 --- a/Box42/Box/View/BoxContentsViewGroup.swift +++ b/Box42/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) @@ -69,7 +69,6 @@ class BoxContentsViewGroup: NSView { } currentWebview.viewDidMoveToSuperview() - currentWebview.becomeFirstResponder() } } diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift index 014f62c..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", "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"), ("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) +// } } 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() } 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 { diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift deleted file mode 100644 index dc69045..0000000 --- a/Box42/Window/BoxWindowController.swift +++ /dev/null @@ -1,138 +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, .titled] - - 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 = BoxViewController(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.setToggleIsShowWindow() - 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/WindowButton/Model/WindowButtonUI.swift b/Box42/WindowButton/Model/WindowButtonUI.swift new file mode 100644 index 0000000..66252be --- /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 + +enum WindowButtonUI { + enum size { + static let diameter = 15 + static let cornerRadius = CGFloat(diameter / 2) + static let offset = 8 + } + + enum animation { + static let duration = TimeInterval(0.2) + } + + enum 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 new file mode 100644 index 0000000..3b5d404 --- /dev/null +++ b/Box42/WindowButton/View/WindowCloseButton.swift @@ -0,0 +1,77 @@ +// +// 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: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + 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) + + 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 + + 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 new file mode 100644 index 0000000..f5a7f3c --- /dev/null +++ b/Box42/WindowButton/View/WindowMaximizeButton.swift @@ -0,0 +1,77 @@ +// +// 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: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + 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) + + 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 + + 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 new file mode 100644 index 0000000..4d6537c --- /dev/null +++ b/Box42/WindowButton/View/WindowMinimizeButton.swift @@ -0,0 +1,77 @@ +// +// 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: WindowButtonUI.size.diameter, height: WindowButtonUI.size.diameter)) + + self.title = "" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.minimize + 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) + + 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 + + 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 new file mode 100644 index 0000000..15ff801 --- /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(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(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(WindowButtonUI.size.offset) + make.width.equalTo(WindowButtonUI.size.diameter) + make.height.equalTo(WindowButtonUI.size.diameter) + } + } +} 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) + } +}