From 2c250e7839741c4228d84450ca2fe84c8df908c8 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 24 Jul 2023 03:07:38 +0900 Subject: [PATCH 01/55] =?UTF-8?q?refactor(Migration=F0=9F=9A=9A):=20MacOS?= =?UTF-8?q?=20=EB=B2=84=EC=A0=84=2010.15.7=EC=9D=98=20=EA=B0=9C=EB=B0=9C?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EC=A3=BC?= =?UTF-8?q?=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 327 +++++++++--------- .../UserInterfaceState.xcuserstate | Bin 94938 -> 0 bytes .../UserInterfaceState.xcuserstate | Bin 0 -> 139610 bytes .../xcshareddata/xcschemes/Box42.xcscheme | 78 ----- .../xcdebugger/Breakpoints_v2.xcbkptlist | 72 ---- .../xcdebugger/Breakpoints_v2.xcbkptlist | 24 ++ .../xcschemes/xcschememanagement.plist | 8 - Box42/Box/BoxController.swift | 268 ++++++++++++++ Box42/Box/BoxModel.swift | 27 ++ Box42/CPU/CPU.swift | 118 +++---- Box42/Main/BoxController.swift | 205 ----------- Box42/Main/BoxModel.swift | 27 -- Box42/Main/BoxView.swift | 12 - Box42/Menubar/MenubarController.swift | 56 +-- Box42/Menubar/MenubarModel.swift | 14 +- Box42/Menubar/MenubarView.swift | 39 ++- Box42/Preferences/Icon.swift | 8 + Box42/Resource/AppDelegate.swift | 173 --------- .../Box42.xcdatamodel/contents | 4 - Box42/Resource/EventMonitor.swift | 34 -- Box42/Resource/Info.plist | 11 - Box42/Resources/AppDelegate.swift | 173 +++++++++ .../42box3/42box_1.imageset/42box_1.png | Bin .../42box3/42box_1.imageset/Contents.json | 0 .../42box3/42box_2.imageset/42box_2.png | Bin .../42box3/42box_2.imageset/Contents.json | 0 .../42box3/42box_3.imageset/42box_3.png | Bin .../42box3/42box_3.imageset/Contents.json | 0 .../42box3/42box_4.imageset/42box_4.png | Bin .../42box3/42box_4.imageset/Contents.json | 0 .../Assets.xcassets/42box3/Contents.json | 0 .../42box_logo 1.imageset/42box_logo.svg | 0 .../42box_logo 1.imageset/Contents.json | 0 .../42box_logo.imageset/42box_logo.png | Bin .../42box_logo.imageset/Contents.json | 0 .../42box_oc1.imageset/42box_opend_black.png | Bin .../42box_oc1.imageset/Contents.json | 0 .../42box_oc2.imageset/42box_closed_black.png | Bin .../42box_oc2.imageset/Contents.json | 0 .../42flip/42flip_01.imageset/42flip_01.png | Bin .../42flip/42flip_01.imageset/Contents.json | 0 .../42flip/42flip_010.imageset/42flip_010.png | Bin .../42flip/42flip_010.imageset/Contents.json | 0 .../42flip/42flip_011.imageset/42flip_011.png | Bin .../42flip/42flip_011.imageset/Contents.json | 0 .../42flip/42flip_02.imageset/42flip_02.png | Bin .../42flip/42flip_02.imageset/Contents.json | 0 .../42flip/42flip_03.imageset/42flip_03.png | Bin .../42flip/42flip_03.imageset/Contents.json | 0 .../42flip/42flip_04.imageset/42flip_04.png | Bin .../42flip/42flip_04.imageset/Contents.json | 0 .../42flip/42flip_05.imageset/42flip_05.png | Bin .../42flip/42flip_05.imageset/Contents.json | 0 .../42flip/42flip_06.imageset/42flip_06.png | Bin .../42flip/42flip_06.imageset/Contents.json | 0 .../42flip/42flip_07.imageset/42flip_07.png | Bin .../42flip/42flip_07.imageset/Contents.json | 0 .../42flip/42flip_08.imageset/42flip_08.png | Bin .../42flip/42flip_08.imageset/Contents.json | 0 .../42flip/42flip_09.imageset/42flip_09.png | Bin .../42flip/42flip_09.imageset/Contents.json | 0 .../42pack_icon/42flip/42flip/Contents.json | 0 .../42pack_icon/42flip/Contents.json | 0 .../Assets.xcassets/42pack_icon/Contents.json | 0 .../42pack_icon/cat/Contents.json | 0 .../cat/cat_page0.imageset/Contents.json | 0 .../cat/cat_page0.imageset/cat0.png | Bin .../cat/cat_page1.imageset/Contents.json | 0 .../cat/cat_page1.imageset/cat1.png | Bin .../cat/cat_page2.imageset/Contents.json | 0 .../cat/cat_page2.imageset/cat2.png | Bin .../cat/cat_page3.imageset/Contents.json | 0 .../cat/cat_page3.imageset/cat3.png | Bin .../cat/cat_page4.imageset/Contents.json | 0 .../cat/cat_page4.imageset/cat4.png | Bin .../42pack_icon/gam/Contents.json | 0 .../gam/gam_1.imageset/Contents.json | 0 .../42pack_icon/gam/gam_1.imageset/gam_1.png | Bin .../gam/gam_2.imageset/Contents.json | 0 .../42pack_icon/gam/gam_2.imageset/gam_2.png | Bin .../gam/gam_3.imageset/Contents.json | 0 .../42pack_icon/gam/gam_3.imageset/gam_3.png | Bin .../gam/gam_4.imageset/Contents.json | 0 .../42pack_icon/gam/gam_4.imageset/gam_4.png | Bin .../gam/gam_5.imageset/Contents.json | 0 .../42pack_icon/gam/gam_5.imageset/gam_5.png | Bin .../42pack_icon/gon/Contents.json | 0 .../gon/gon_1.imageset/Contents.json | 0 .../42pack_icon/gon/gon_1.imageset/gon_1.png | Bin .../gon/gon_2.imageset/Contents.json | 0 .../42pack_icon/gon/gon_2.imageset/gon_2.png | Bin .../gon/gon_3.imageset/Contents.json | 0 .../42pack_icon/gon/gon_3.imageset/gon_3.png | Bin .../gon/gon_4.imageset/Contents.json | 0 .../42pack_icon/gon/gon_4.imageset/gon_4.png | Bin .../gon/gon_5.imageset/Contents.json | 0 .../42pack_icon/gon/gon_5.imageset/gon_5.png | Bin .../42pack_icon/gun/Contents.json | 0 .../gun/gun_1.imageset/Contents.json | 0 .../42pack_icon/gun/gun_1.imageset/gun_1.png | Bin .../gun/gun_2.imageset/Contents.json | 0 .../42pack_icon/gun/gun_2.imageset/gun_2.png | Bin .../gun/gun_3.imageset/Contents.json | 0 .../42pack_icon/gun/gun_3.imageset/gun_3.png | Bin .../gun/gun_4.imageset/Contents.json | 0 .../42pack_icon/gun/gun_4.imageset/gun_4.png | Bin .../gun/gun_5.imageset/Contents.json | 0 .../42pack_icon/gun/gun_5.imageset/gun_5.png | Bin .../42pack_icon/lee/Contents.json | 0 .../lee/lee_1.imageset/Contents.json | 0 .../42pack_icon/lee/lee_1.imageset/lee_1.png | Bin .../lee/lee_2.imageset/Contents.json | 0 .../42pack_icon/lee/lee_2.imageset/lee_2.png | Bin .../lee/lee_3.imageset/Contents.json | 0 .../42pack_icon/lee/lee_3.imageset/lee_3.png | Bin .../lee/lee_4.imageset/Contents.json | 0 .../42pack_icon/lee/lee_4.imageset/lee_4.png | Bin .../lee/lee_5.imageset/Contents.json | 0 .../42pack_icon/lee/lee_5.imageset/lee_5.png | Bin .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/1024.png | Bin .../AppIcon.appiconset/128.png | Bin .../Assets.xcassets/AppIcon.appiconset/16.png | Bin .../AppIcon.appiconset/256.png | Bin .../Assets.xcassets/AppIcon.appiconset/32.png | Bin .../AppIcon.appiconset/512.png | Bin .../Assets.xcassets/AppIcon.appiconset/64.png | Bin .../AppIcon.appiconset/Contents.json | 0 .../Assets.xcassets/AppIcons/Contents.json | 0 .../AppIcons/appstore.imageset/Contents.json | 0 .../AppIcons/appstore.imageset/appstore.png | Bin .../AppIcons/playstore.imageset/Contents.json | 0 .../AppIcons/playstore.imageset/playstore.png | Bin .../Assets.xcassets/Contents.json | 0 .../Box42.entitlements | 0 .../Box42.xcdatamodeld/.xccurrentversion | 0 .../Box42.xcdatamodel/contents | 4 + Box42/Resources/EventMonitor.swift | 34 ++ Box42/Resources/Info.plist | 32 ++ Box42/{Resource => Resources}/Main.storyboard | 104 ++++-- Box42/Resources/StringExtension.swift | 21 ++ Box42/URL/URLModel.swift | 52 +-- Box42/Web/WebViewController.swift | 53 --- Box42/Web/WebViewModel.swift | 20 -- Box42/WebView/WebViewController.swift | 58 ++++ Box42/WebView/WebViewModel.swift | 19 + 146 files changed, 1054 insertions(+), 1021 deletions(-) delete mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/chan.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme delete mode 100644 Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist rename Box42.xcodeproj/xcuserdata/{chan.xcuserdatad => chanheki.xcuserdatad}/xcschemes/xcschememanagement.plist (69%) create mode 100644 Box42/Box/BoxController.swift create mode 100644 Box42/Box/BoxModel.swift delete mode 100644 Box42/Main/BoxController.swift delete mode 100644 Box42/Main/BoxModel.swift delete mode 100644 Box42/Main/BoxView.swift create mode 100644 Box42/Preferences/Icon.swift delete mode 100644 Box42/Resource/AppDelegate.swift delete mode 100644 Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents delete mode 100644 Box42/Resource/EventMonitor.swift delete mode 100644 Box42/Resource/Info.plist create mode 100644 Box42/Resources/AppDelegate.swift rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_1.imageset/42box_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_2.imageset/42box_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_3.imageset/42box_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_4.imageset/42box_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo 1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo.imageset/42box_logo.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/1024.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/128.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/16.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/256.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/32.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/512.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/64.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/appstore.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/appstore.imageset/appstore.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/playstore.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/playstore.imageset/playstore.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/Contents.json (100%) rename Box42/{Resource => Resources}/Box42.entitlements (100%) rename Box42/{Resource => Resources}/Box42.xcdatamodeld/.xccurrentversion (100%) create mode 100644 Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents create mode 100644 Box42/Resources/EventMonitor.swift create mode 100644 Box42/Resources/Info.plist rename Box42/{Resource => Resources}/Main.storyboard (71%) create mode 100644 Box42/Resources/StringExtension.swift delete mode 100644 Box42/Web/WebViewController.swift delete mode 100644 Box42/Web/WebViewModel.swift create mode 100644 Box42/WebView/WebViewController.swift create mode 100644 Box42/WebView/WebViewModel.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 5cdc368..8fbe226 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -3,50 +3,60 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ - 6450C99B29C1D5A3001D429E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C99A29C1D5A3001D429E /* AppDelegate.swift */; }; - 6450C9A029C1D5A3001D429E /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 6450C99E29C1D5A3001D429E /* Box42.xcdatamodeld */; }; - 6450C9A229C1D5A5001D429E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6450C9A129C1D5A5001D429E /* Assets.xcassets */; }; - 6450C9BD29C32972001D429E /* BoxController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9BB29C32972001D429E /* BoxController.swift */; }; - 6450C9BE29C32972001D429E /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9BC29C32972001D429E /* EventMonitor.swift */; }; - 6450C9C429C32A90001D429E /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9C329C32A90001D429E /* WebViewController.swift */; }; - 6450C9C729C32AAC001D429E /* URLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9C629C32AAC001D429E /* URLModel.swift */; }; - 6450C9CA29C32D63001D429E /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9C929C32D63001D429E /* CPU.swift */; }; - 6450C9CD29C32DBB001D429E /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9CC29C32DBB001D429E /* MenubarModel.swift */; }; - 6450C9CF29C32E34001D429E /* BoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9CE29C32E34001D429E /* BoxModel.swift */; }; - 6450C9D129C330C3001D429E /* MenubarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9D029C330C3001D429E /* MenubarController.swift */; }; - 6450C9D329C33105001D429E /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6450C9D229C33105001D429E /* MenubarView.swift */; }; - 64DF818A29C3B88B000B32F4 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64DF818929C3B88B000B32F4 /* BoxView.swift */; }; - 64DF818C29C4AA85000B32F4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64DF818B29C4AA85000B32F4 /* Main.storyboard */; }; - 64DF818F29C61033000B32F4 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64DF818E29C61033000B32F4 /* WebViewModel.swift */; }; + DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */; }; + DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */; }; + DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */; }; + DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */; }; + DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE32A509B1700FF0AA3 /* CPU.swift */; }; + DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */; }; + DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */; }; + DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEC2A509B2600FF0AA3 /* URLModel.swift */; }; + DE018BF02A509B2F00FF0AA3 /* MenubarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEF2A509B2F00FF0AA3 /* MenubarController.swift */; }; + DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; + DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; + DE018BF92A509B3B00FF0AA3 /* BoxController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF82A509B3B00FF0AA3 /* BoxController.swift */; }; + DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */; }; + DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFE2A509B4200FF0AA3 /* BoxView.swift */; }; + DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; + DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesController.swift */; }; + 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 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 6450C99729C1D5A3001D429E /* Box42.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Box42.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6450C99A29C1D5A3001D429E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 6450C99F29C1D5A3001D429E /* Box42.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Box42.xcdatamodel; sourceTree = ""; }; - 6450C9A129C1D5A5001D429E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6450C9A629C1D5A5001D429E /* Box42.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; - 6450C9B429C2343D001D429E /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 6450C9BB29C32972001D429E /* BoxController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxController.swift; sourceTree = ""; }; - 6450C9BC29C32972001D429E /* EventMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; - 6450C9C329C32A90001D429E /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; - 6450C9C629C32AAC001D429E /* URLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLModel.swift; sourceTree = ""; }; - 6450C9C929C32D63001D429E /* CPU.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = ""; }; - 6450C9CC29C32DBB001D429E /* MenubarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; - 6450C9CE29C32E34001D429E /* BoxModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxModel.swift; sourceTree = ""; }; - 6450C9D029C330C3001D429E /* MenubarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarController.swift; sourceTree = ""; }; - 6450C9D229C33105001D429E /* MenubarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; - 64DF818929C3B88B000B32F4 /* BoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; - 64DF818B29C4AA85000B32F4 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; - 64DF818E29C61033000B32F4 /* WebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = ""; }; + DE018BAF2A5099F900FF0AA3 /* Box42.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Box42.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Box42.xcdatamodel; sourceTree = ""; }; + DE018BBE2A5099FA00FF0AA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; + DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DE018BE32A509B1700FF0AA3 /* CPU.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = ""; }; + DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; + DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = ""; }; + DE018BEC2A509B2600FF0AA3 /* URLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLModel.swift; sourceTree = ""; }; + DE018BEF2A509B2F00FF0AA3 /* MenubarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarController.swift; sourceTree = ""; }; + DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; + DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; + DE018BF82A509B3B00FF0AA3 /* BoxController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxController.swift; sourceTree = ""; }; + DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxModel.swift; sourceTree = ""; }; + DE018BFE2A509B4200FF0AA3 /* BoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; + DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; + DE7A25792A6D8CA20043225A /* PreferencesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesController.swift; 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 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 6450C99429C1D5A3001D429E /* Frameworks */ = { + DE018BAC2A5099F900FF0AA3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -56,112 +66,125 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 6450C98E29C1D5A3001D429E = { + DE018BA62A5099F900FF0AA3 = { isa = PBXGroup; children = ( - 6450C99929C1D5A3001D429E /* Box42 */, - 6450C99829C1D5A3001D429E /* Products */, - 6450C9B329C2343D001D429E /* Frameworks */, + DE018BB12A5099F900FF0AA3 /* Box42 */, + DE018BB02A5099F900FF0AA3 /* Products */, ); sourceTree = ""; }; - 6450C99829C1D5A3001D429E /* Products */ = { + DE018BB02A5099F900FF0AA3 /* Products */ = { isa = PBXGroup; children = ( - 6450C99729C1D5A3001D429E /* Box42.app */, + DE018BAF2A5099F900FF0AA3 /* Box42.app */, ); name = Products; sourceTree = ""; }; - 6450C99929C1D5A3001D429E /* Box42 */ = { + DE018BB12A5099F900FF0AA3 /* Box42 */ = { isa = PBXGroup; children = ( - 6450C9CB29C32DB1001D429E /* Menubar */, - 6450C9C529C32AAC001D429E /* URL */, - 6450C9C829C32D54001D429E /* CPU */, - 6450C9C229C32A90001D429E /* Web */, - 6450C9BF29C3299F001D429E /* Resource */, - 6450C9BA29C32972001D429E /* Main */, + DE874F512A591EC600FC3B77 /* Preferences */, + DE874F4C2A591DC400FC3B77 /* Hotkey */, + DE018C0C2A509BDF00FF0AA3 /* Resources */, + DE018C062A509B9000FF0AA3 /* CPU */, + DE018C082A509BB500FF0AA3 /* WebView */, + DE018C0B2A509BC100FF0AA3 /* URL */, + DE018C0E2A509C0C00FF0AA3 /* Menubar */, + DE018C102A509C1A00FF0AA3 /* Box */, ); path = Box42; sourceTree = ""; }; - 6450C9B329C2343D001D429E /* Frameworks */ = { + DE018C062A509B9000FF0AA3 /* CPU */ = { isa = PBXGroup; children = ( - 6450C9B429C2343D001D429E /* WebKit.framework */, + DE018BE32A509B1700FF0AA3 /* CPU.swift */, ); - name = Frameworks; + path = CPU; sourceTree = ""; }; - 6450C9BA29C32972001D429E /* Main */ = { + DE018C082A509BB500FF0AA3 /* WebView */ = { isa = PBXGroup; children = ( - 6450C9BB29C32972001D429E /* BoxController.swift */, - 6450C9CE29C32E34001D429E /* BoxModel.swift */, - 64DF818929C3B88B000B32F4 /* BoxView.swift */, + DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, + DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, ); - path = Main; + path = WebView; sourceTree = ""; }; - 6450C9BF29C3299F001D429E /* Resource */ = { + DE018C0B2A509BC100FF0AA3 /* URL */ = { isa = PBXGroup; children = ( - 6450C99A29C1D5A3001D429E /* AppDelegate.swift */, - 6450C9BC29C32972001D429E /* EventMonitor.swift */, - 6450C9A129C1D5A5001D429E /* Assets.xcassets */, - 64DF818B29C4AA85000B32F4 /* Main.storyboard */, - 6450C9A629C1D5A5001D429E /* Box42.entitlements */, - 6450C99E29C1D5A3001D429E /* Box42.xcdatamodeld */, + DE018BEC2A509B2600FF0AA3 /* URLModel.swift */, ); - path = Resource; + path = URL; sourceTree = ""; }; - 6450C9C229C32A90001D429E /* Web */ = { + DE018C0C2A509BDF00FF0AA3 /* Resources */ = { isa = PBXGroup; children = ( - 6450C9C329C32A90001D429E /* WebViewController.swift */, - 64DF818E29C61033000B32F4 /* WebViewModel.swift */, + DE018C192A509DBA00FF0AA3 /* Box42.entitlements */, + DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */, + DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, + DE018BBE2A5099FA00FF0AA3 /* Info.plist */, + DE018C022A509B5D00FF0AA3 /* Main.storyboard */, + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, + DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */, + DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */, ); - path = Web; + path = Resources; sourceTree = ""; }; - 6450C9C529C32AAC001D429E /* URL */ = { + DE018C0E2A509C0C00FF0AA3 /* Menubar */ = { isa = PBXGroup; children = ( - 6450C9C629C32AAC001D429E /* URLModel.swift */, + DE018BEF2A509B2F00FF0AA3 /* MenubarController.swift */, + DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */, + DE018BF52A509B3600FF0AA3 /* MenubarView.swift */, ); - path = URL; + path = Menubar; sourceTree = ""; }; - 6450C9C829C32D54001D429E /* CPU */ = { + DE018C102A509C1A00FF0AA3 /* Box */ = { isa = PBXGroup; children = ( - 6450C9C929C32D63001D429E /* CPU.swift */, + DE018BF82A509B3B00FF0AA3 /* BoxController.swift */, + DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */, + DE018BFE2A509B4200FF0AA3 /* BoxView.swift */, ); - path = CPU; + path = Box; sourceTree = ""; }; - 6450C9CB29C32DB1001D429E /* Menubar */ = { + DE874F4C2A591DC400FC3B77 /* Hotkey */ = { isa = PBXGroup; children = ( - 6450C9CC29C32DBB001D429E /* MenubarModel.swift */, - 6450C9D029C330C3001D429E /* MenubarController.swift */, - 6450C9D229C33105001D429E /* MenubarView.swift */, + DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */, ); - path = Menubar; + path = Hotkey; + sourceTree = ""; + }; + DE874F512A591EC600FC3B77 /* Preferences */ = { + isa = PBXGroup; + children = ( + DE7A25792A6D8CA20043225A /* PreferencesController.swift */, + DE874F532A591F1400FC3B77 /* PreferencesView.swift */, + DE874F562A591F2500FC3B77 /* Icon.swift */, + ); + path = Preferences; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 6450C99629C1D5A3001D429E /* Box42 */ = { + DE018BAE2A5099F900FF0AA3 /* Box42 */ = { isa = PBXNativeTarget; - buildConfigurationList = 6450C9A929C1D5A5001D429E /* Build configuration list for PBXNativeTarget "Box42" */; + buildConfigurationList = DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */; buildPhases = ( - 6450C99329C1D5A3001D429E /* Sources */, - 6450C99429C1D5A3001D429E /* Frameworks */, - 6450C99529C1D5A3001D429E /* Resources */, + DE018BAB2A5099F900FF0AA3 /* Sources */, + DE018BAC2A5099F900FF0AA3 /* Frameworks */, + DE018BAD2A5099F900FF0AA3 /* Resources */, ); buildRules = ( ); @@ -169,85 +192,90 @@ ); name = Box42; productName = Box42; - productReference = 6450C99729C1D5A3001D429E /* Box42.app */; + productReference = DE018BAF2A5099F900FF0AA3 /* Box42.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 6450C98F29C1D5A3001D429E /* Project object */ = { + DE018BA72A5099F900FF0AA3 /* Project object */ = { isa = PBXProject; attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1400; - LastUpgradeCheck = 1400; + LastSwiftUpdateCheck = 1230; + LastUpgradeCheck = 1230; TargetAttributes = { - 6450C99629C1D5A3001D429E = { - CreatedOnToolsVersion = 14.0.1; + DE018BAE2A5099F900FF0AA3 = { + CreatedOnToolsVersion = 12.3; }; }; }; - buildConfigurationList = 6450C99229C1D5A3001D429E /* Build configuration list for PBXProject "Box42" */; - compatibilityVersion = "Xcode 14.0"; + buildConfigurationList = DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */; + compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = 6450C98E29C1D5A3001D429E; - productRefGroup = 6450C99829C1D5A3001D429E /* Products */; + mainGroup = DE018BA62A5099F900FF0AA3; + productRefGroup = DE018BB02A5099F900FF0AA3 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 6450C99629C1D5A3001D429E /* Box42 */, + DE018BAE2A5099F900FF0AA3 /* Box42 */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 6450C99529C1D5A3001D429E /* Resources */ = { + DE018BAD2A5099F900FF0AA3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6450C9A229C1D5A5001D429E /* Assets.xcassets in Resources */, - 64DF818C29C4AA85000B32F4 /* Main.storyboard in Resources */, + DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */, + DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 6450C99329C1D5A3001D429E /* Sources */ = { + DE018BAB2A5099F900FF0AA3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 64DF818F29C61033000B32F4 /* WebViewModel.swift in Sources */, - 6450C9D129C330C3001D429E /* MenubarController.swift in Sources */, - 6450C9D329C33105001D429E /* MenubarView.swift in Sources */, - 6450C9CF29C32E34001D429E /* BoxModel.swift in Sources */, - 6450C9CD29C32DBB001D429E /* MenubarModel.swift in Sources */, - 6450C9A029C1D5A3001D429E /* Box42.xcdatamodeld in Sources */, - 6450C9C729C32AAC001D429E /* URLModel.swift in Sources */, - 6450C9CA29C32D63001D429E /* CPU.swift in Sources */, - 6450C9BD29C32972001D429E /* BoxController.swift in Sources */, - 64DF818A29C3B88B000B32F4 /* BoxView.swift in Sources */, - 6450C9BE29C32972001D429E /* EventMonitor.swift in Sources */, - 6450C9C429C32A90001D429E /* WebViewController.swift in Sources */, - 6450C99B29C1D5A3001D429E /* AppDelegate.swift in Sources */, + DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */, + DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, + DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, + DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, + DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, + DE018BF92A509B3B00FF0AA3 /* BoxController.swift in Sources */, + DE018BF02A509B2F00FF0AA3 /* MenubarController.swift in Sources */, + DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, + DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, + DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, + DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, + DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, + DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */, + DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, + DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */, + DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, + DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, + DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - 6450C9A729C1D5A5001D429E /* Debug */ = { + DE018BC02A5099FA00FF0AA3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -291,7 +319,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -301,13 +329,14 @@ }; name = Debug; }; - 6450C9A829C1D5A5001D429E /* Release */ = { + DE018BC12A5099FA00FF0AA3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -345,7 +374,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -354,64 +383,40 @@ }; name = Release; }; - 6450C9AA29C1D5A5001D429E /* Debug */ = { + DE018BC32A5099FA00FF0AA3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = Box42/Resource/Box42.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_ENTITLEMENTS = Box42/Box42.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8CB4B27BA3; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = Box42/Resource/Info.plist; - INFOPLIST_KEY_LSUIElement = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSPrincipalClass = NSApplication; + INFOPLIST_FILE = Box42/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = chanheki.Box42; + PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; - 6450C9AB29C1D5A5001D429E /* Release */ = { + DE018BC42A5099FA00FF0AA3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = Box42/Resource/Box42.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_ENTITLEMENTS = Box42/Box42.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8CB4B27BA3; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = Box42/Resource/Info.plist; - INFOPLIST_KEY_LSUIElement = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSPrincipalClass = NSApplication; + INFOPLIST_FILE = Box42/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = chanheki.Box42; + PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; @@ -419,20 +424,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 6450C99229C1D5A3001D429E /* Build configuration list for PBXProject "Box42" */ = { + DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6450C9A729C1D5A5001D429E /* Debug */, - 6450C9A829C1D5A5001D429E /* Release */, + DE018BC02A5099FA00FF0AA3 /* Debug */, + DE018BC12A5099FA00FF0AA3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6450C9A929C1D5A5001D429E /* Build configuration list for PBXNativeTarget "Box42" */ = { + DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6450C9AA29C1D5A5001D429E /* Debug */, - 6450C9AB29C1D5A5001D429E /* Release */, + DE018BC32A5099FA00FF0AA3 /* Debug */, + DE018BC42A5099FA00FF0AA3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -440,17 +445,17 @@ /* End XCConfigurationList section */ /* Begin XCVersionGroup section */ - 6450C99E29C1D5A3001D429E /* Box42.xcdatamodeld */ = { + DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */ = { isa = XCVersionGroup; children = ( - 6450C99F29C1D5A3001D429E /* Box42.xcdatamodel */, + DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */, ); - currentVersion = 6450C99F29C1D5A3001D429E /* Box42.xcdatamodel */; + currentVersion = DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */; path = Box42.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; }; /* End XCVersionGroup section */ }; - rootObject = 6450C98F29C1D5A3001D429E /* Project object */; + rootObject = DE018BA72A5099F900FF0AA3 /* Project object */; } diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chan.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chan.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index d80a4ee8039c6d373c7be87865d7302ead383320..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94938 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�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

1|F& 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 S`s=?#2mSTm|NlEIFZnMxmQPUt literal 0 HcmV?d00001 diff --git a/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme b/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme deleted file mode 100644 index e2816e4..0000000 --- a/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index e33adfe..0000000 --- a/Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..e9d969f --- /dev/null +++ b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcschemes/xcschememanagement.plist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 69% rename from Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcschemes/xcschememanagement.plist rename to Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist index d631b0f..2d4f387 100644 --- a/Box42.xcodeproj/xcuserdata/chan.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist @@ -10,13 +10,5 @@ 0 - SuppressBuildableAutocreation - - 6450C99629C1D5A3001D429E - - primary - - - diff --git a/Box42/Box/BoxController.swift b/Box42/Box/BoxController.swift new file mode 100644 index 0000000..0c5b533 --- /dev/null +++ b/Box42/Box/BoxController.swift @@ -0,0 +1,268 @@ +// +// BoxViewController.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import Cocoa +import AppKit +import WebKit + +class BoxController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { + var ad = NSApplication.shared.delegate as? AppDelegate + let url = URLModel() + var wvc = WebViewController() + let preferencesVC = PreferencesViewController() + + var topAnchorDistance: CGFloat = 0 + + @IBOutlet var divider: NSBox! + @IBOutlet weak var boxView: NSView! + @IBOutlet weak var buttonViewGroup: NSView! + @IBOutlet weak var hostingViewGroup: NSView! + @IBOutlet var pinSwitch: NSSwitch! + + private var webView: WKWebView! + private var buttonBoxGroup: NSView! + + override func keyDown(with event: NSEvent) { + if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { + // 복사 동작 처리 + webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in + if let error = error { + print("Copy error: \(error)") + } else { + print("Copy success") + } + } + } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { + // 붙여넣기 동작 처리 + let pasteboard = NSPasteboard.general + if let pasteString = pasteboard.string(forType: .string) { + let escapedPasteString = pasteString.escapedForJavaScript + webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in + if let error = error { + print("Paste error: \(error)") + } else { + print("Paste success") + } + } + } + } else { + super.keyDown(with: event) // 기본 키 이벤트 처리 + } + } + + override func viewDidLoad() { + view.window?.makeFirstResponder(self) + super.viewDidLoad() + buttonBoxGroupInit() + boxViewSizeInit() + webViewInit() + wvc.loadWebViewInit() + configureButton() + } + + func createButton(_ title :String) { + let button = NSButton() + + button.title = title + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(self.clickBtn(sender:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 30 + button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createHomeButton() { + let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: (Any).self, action: #selector(self.clickBtn(sender:))) + button.translatesAutoresizingMaskIntoConstraints = false + button.isBordered = false + button.imagePosition = .imageOnly + + buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 80 + button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createQuitButton() { + let button = NSButton() + button.title = "Quit Box" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(NSApplication.terminate(_:)) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -10).isActive = true + button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func divide() { + divider.translatesAutoresizingMaskIntoConstraints = false + divider.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -40).isActive = true + } + + func createPinButton() { + let button = NSButton() + button.title = "Pin Box" + button.setButtonType(.toggle) + button.contentTintColor = .orange + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(self.pin) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -50).isActive = true + button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func preferencesButton() { + let button = NSButton() + button.title = "Preferences" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(self.clickBtn(sender:)) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -90).isActive = true + button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func configureButton() { + createHomeButton() + for i in 1.. 2 { + let rqURL = URLRequest(url: URLModel().URLdict[sender.title]!) + WebViewList.shared.list[sender.title]!.load(rqURL) + print("Triple Click") + } else if clickCount < 2 { + hostingViewGroup.subviews.removeAll() + hostingViewGroup.addSubview(WebViewList.shared.list[sender.title]!) + WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true + WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true + WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() + setAutoLayout(from: WebViewList.shared.list[sender.title]!, to: hostingViewGroup) + } + } + + @objc + func pin(_ sender: NSSwitch) { + ad?.boxStatus.isPin.toggle() + print(sender.state) + } + + func boxViewSizeInit() { + boxView.frame.size.width = BoxViewSize().size.width + boxView.frame.size.height = BoxViewSize().size.height + + hostingViewGroup.frame.size.width = BoxViewSize().size.width - BoxViewSize().buttonGroupSize.width + hostingViewGroup.frame.size.height = BoxViewSize().size.height + + buttonViewGroup.frame.size.width = BoxViewSize().buttonGroupSize.width + buttonViewGroup.frame.size.height = BoxViewSize().buttonGroupSize.height + } + + func buttonBoxGroupInit() { + buttonBoxGroup = NSView(frame: NSRect(x: 0, y: 0, width: BoxViewSize().buttonGroupSize.width, height: BoxViewSize().buttonGroupSize.height)) + buttonBoxGroup.frame.size.width = BoxViewSize().buttonGroupSize.width + buttonBoxGroup.frame.size.height = BoxViewSize().buttonGroupSize.height + buttonViewGroup.addSubview(buttonBoxGroup) + + setAutoLayout(from: buttonBoxGroup, to: buttonViewGroup) + } + + func webViewInit() { + webView = wvc.addWebView() + hostingViewGroup.addSubview(webView) + setAutoLayout(from: webView, to: hostingViewGroup) + let request = URLRequest(url: url.URLdict["home"]!) + DispatchQueue.main.async { + self.webView.load(request) + } + } + + public func setAutoLayout(from: NSView, to: NSView) { + from.translatesAutoresizingMaskIntoConstraints = false + to.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true + view.layout() + } + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + print(message.name) + } +} + +extension BoxController { + static func freshController() -> BoxController { + let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) + let identifier = NSStoryboard.SceneIdentifier("BoxController") + + guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxController else { + fatalError("Story Board Not Found") + } + return viewcontroller + } +} diff --git a/Box42/Box/BoxModel.swift b/Box42/Box/BoxModel.swift new file mode 100644 index 0000000..b188c95 --- /dev/null +++ b/Box42/Box/BoxModel.swift @@ -0,0 +1,27 @@ +// +// BoxViewModel.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import WebKit + +public extension NSScreen { + static let screenSize = NSScreen.main?.visibleFrame.size + static let screenWidth = screenSize!.width + static let screenHeight = screenSize!.height + static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) + static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) +} + +public struct BoxViewSize { + var halfSize: (width: CGFloat, height: CGFloat) = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) + var size: (width: CGFloat, height: CGFloat) = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) + var buttonGroupSize: (width: CGFloat, height: CGFloat) = (CGFloat(132), NSScreen.customScreenSize.y) + var viewStack = [NSView()] +} + +public class BoxStatus { + var isPin: Bool = false +} diff --git a/Box42/CPU/CPU.swift b/Box42/CPU/CPU.swift index 35b4e66..33c11a9 100644 --- a/Box42/CPU/CPU.swift +++ b/Box42/CPU/CPU.swift @@ -9,63 +9,63 @@ import Foundation public class CPU { - var cpuTimer: Timer? = nil - var isShow: Bool = false - var usage: (value: Double, description: String) = (0.0, "") - - private let loadInfoCount: mach_msg_type_number_t! - private var loadPrevious = host_cpu_load_info() - - init() { - loadInfoCount = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) - } - - private func hostCPULoadInfo() -> host_cpu_load_info { - var size: mach_msg_type_number_t = loadInfoCount - let hostInfo = host_cpu_load_info_t.allocate(capacity: 1) - let _ = hostInfo.withMemoryRebound(to: integer_t.self, capacity: Int(size)) { - return host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size) - } - let data = hostInfo.move() - hostInfo.deallocate() - return data - } - - public func usageCPU() { - let load = hostCPULoadInfo() - let userDiff = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0) - let sysDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1) - let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2) - let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3) - loadPrevious = load - - let totalTicks = sysDiff + userDiff + idleDiff + niceDiff - let sys = 100.0 * sysDiff / totalTicks - let user = 100.0 * userDiff / totalTicks - - let value: Double = round((sys + user) * 10.0) / 10.0 - let description: String = (value >= 100.0) ? "100↑%" : ((value < 10.0 ? " " : "") + String(value)) + "% " - - self.usage = (value, description) - } - - public func isShowUsage() -> Bool { - if isShow == false { return false } - return true - } - - public func processCPU(_ statusBar: StatusBar) -> Bool { - 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 = self.isShowUsage() ? self.usage.description : "" - }) - self.cpuTimer?.fire() - return true - } - - public func StopCPU() -> Bool { - self.cpuTimer?.invalidate() - return false - } + var cpuTimer: Timer? = nil + var isShow: Bool = false + var usage: (value: Double, description: String) = (0.0, "") + + private let loadInfoCount: mach_msg_type_number_t! + private var loadPrevious = host_cpu_load_info() + + init() { + loadInfoCount = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) + } + + private func hostCPULoadInfo() -> host_cpu_load_info { + var size: mach_msg_type_number_t = loadInfoCount + let hostInfo = host_cpu_load_info_t.allocate(capacity: 1) + let _ = hostInfo.withMemoryRebound(to: integer_t.self, capacity: Int(size)) { + return host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size) + } + let data = hostInfo.move() + hostInfo.deallocate() + return data + } + + public func usageCPU() { + let load = hostCPULoadInfo() + let userDiff = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0) + let sysDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1) + let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2) + let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3) + loadPrevious = load + + let totalTicks = sysDiff + userDiff + idleDiff + niceDiff + let sys = 100.0 * sysDiff / totalTicks + let user = 100.0 * userDiff / totalTicks + + let value: Double = round((sys + user) * 10.0) / 10.0 + let description: String = (value >= 100.0) ? "100↑%" : ((value < 10.0 ? " " : "") + String(value)) + "% " + + self.usage = (value, description) + } + + public func isShowUsage() -> Bool { + if isShow == false { return false } + return true + } + + public func processCPU(_ statusBar: StatusBar) -> Bool { + 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 = self.isShowUsage() ? self.usage.description : "" + }) + self.cpuTimer?.fire() + return true + } + + public func StopCPU() -> Bool { + self.cpuTimer?.invalidate() + return false + } } diff --git a/Box42/Main/BoxController.swift b/Box42/Main/BoxController.swift deleted file mode 100644 index 39babf2..0000000 --- a/Box42/Main/BoxController.swift +++ /dev/null @@ -1,205 +0,0 @@ -// -// BoxViewController.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Cocoa -import AppKit -import WebKit - -class BoxController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - var ad = NSApplication.shared.delegate as? AppDelegate - let url = URLModel() - var wvc = WebViewController() - var topAnchorDistance: CGFloat = 0 - - @IBOutlet var divider: NSBox! - @IBOutlet weak var boxView: NSView! - @IBOutlet weak var buttonViewGroup: NSView! - @IBOutlet weak var hostingViewGroup: NSView! - @IBOutlet var pinSwitch: NSSwitch! - - private var webView: WKWebView! - private var buttonBoxGroup: NSView! - - override func viewDidLoad() { - super.viewDidLoad() - buttonBoxGroupInit() - boxViewSizeInit() - webViewInit() - wvc.loadWebViewInit() - configureButton() - } - - func createButton(_ title :String) { - let button = NSButton() - - button.title = title - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(self.clickBtn(sender:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 30 - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createHomeButton() { - let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: (Any).self, action: #selector(self.clickBtn(sender:))) - button.translatesAutoresizingMaskIntoConstraints = false - button.isBordered = false - button.imagePosition = .imageOnly - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 80 - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createQuitButton() { - let button = NSButton() - button.title = "Quit Box" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(NSApplication.terminate(_:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -10).isActive = true - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func divide() { - divider.translatesAutoresizingMaskIntoConstraints = false - divider.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -40).isActive = true - } - - func createPinButton() { - let button = NSButton() - button.title = "Pin Box" - button.setButtonType(.toggle) - button.contentTintColor = .orange - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(self.pin) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -50).isActive = true - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func configureButton() { - createHomeButton() - for i in 1.. 2{ - let rqURL = URLRequest(url: URLModel().URLdict[sender.title]!) - WebViewList.shared.list[sender.title]!.load(rqURL) - print("Triple Click") - } else if clickCount < 2{ - webView.removeFromSuperview() - hostingViewGroup.addSubview(WebViewList.shared.list[sender.title]!) - setAutoLayout(from: WebViewList.shared.list[sender.title]!, to: hostingViewGroup) - } - } - - @objc - func pin(_ sender: NSSwitch) { - ad?.boxStatus.isPin.toggle() - print(sender.state) - } - - func boxViewSizeInit() { - boxView.frame.size.width = BoxViewSize().size.width - boxView.frame.size.height = BoxViewSize().size.height - - hostingViewGroup.frame.size.width = BoxViewSize().size.width - BoxViewSize().buttonGroupSize.width - hostingViewGroup.frame.size.height = BoxViewSize().size.height - - buttonViewGroup.frame.size.width = BoxViewSize().buttonGroupSize.width - buttonViewGroup.frame.size.height = BoxViewSize().buttonGroupSize.height - } - - func buttonBoxGroupInit() { - buttonBoxGroup = NSView(frame: NSRect(x: 0, y: 0, width: BoxViewSize().buttonGroupSize.width, height: BoxViewSize().buttonGroupSize.height)) - buttonBoxGroup.frame.size.width = BoxViewSize().buttonGroupSize.width - buttonBoxGroup.frame.size.height = BoxViewSize().buttonGroupSize.height - buttonViewGroup.addSubview(buttonBoxGroup) - - setAutoLayout(from: buttonBoxGroup, to: buttonViewGroup) - } - - func webViewInit() { - webView = wvc.addWebView() - hostingViewGroup.addSubview(webView) - setAutoLayout(from: webView, to: hostingViewGroup) - let request = URLRequest(url: url.URLdict["home"]!) - DispatchQueue.main.async { - self.webView.load(request) - } - } - - public func setAutoLayout(from: NSView, to: NSView) { - from.translatesAutoresizingMaskIntoConstraints = false - to.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true - view.layout() - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - print(message.name) - } -} - -extension BoxController { - static func freshController() -> BoxController { - let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) - let identifier = NSStoryboard.SceneIdentifier("BoxController") - - guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxController else { - fatalError("Story Board Not Found") - } - return viewcontroller - } -} diff --git a/Box42/Main/BoxModel.swift b/Box42/Main/BoxModel.swift deleted file mode 100644 index 9600b4b..0000000 --- a/Box42/Main/BoxModel.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// BoxViewModel.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import WebKit - -public extension NSScreen { - static let screenSize = NSScreen.main?.visibleFrame.size - static let screenWidth = screenSize!.width - static let screenHeight = screenSize!.height - static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) - static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) -} - -public struct BoxViewSize { - var halfSize: (width: CGFloat, height: CGFloat) = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) - var size: (width: CGFloat, height: CGFloat) = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) - var buttonGroupSize: (width: CGFloat, height: CGFloat) = (CGFloat(132), NSScreen.customScreenSize.y) - var viewStack = [NSView()] -} - -public class BoxStatus { - var isPin: Bool = false -} diff --git a/Box42/Main/BoxView.swift b/Box42/Main/BoxView.swift deleted file mode 100644 index 4221953..0000000 --- a/Box42/Main/BoxView.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// BoxView.swift -// Box42 -// -// Created by Chan on 2023/03/17. -// - -import Cocoa - -class BoxView: NSView { - -} diff --git a/Box42/Menubar/MenubarController.swift b/Box42/Menubar/MenubarController.swift index 2287c9d..8ac85ac 100644 --- a/Box42/Menubar/MenubarController.swift +++ b/Box42/Menubar/MenubarController.swift @@ -10,30 +10,34 @@ import Foundation import AppKit class MenuBarController: NSWorkspace { - let cpu = CPU() - let statusBar = StatusBar() - let menuBarView = MenuBarView() - - func buttonInit() { - menuBarView.imageInit("box", statusBar) - menuBarView.buttonAppear(statusBar) - } - - func startRunning() { - statusBar.isRunning = cpu.processCPU(statusBar) - animate() - } - - func stopRunning() { - statusBar.isRunning = cpu.StopCPU() - } - - func animate() { - statusBar.statusItem.button?.image = statusBar.frames[statusBar.cnt] - statusBar.cnt = (statusBar.cnt + 1) % statusBar.frames.count - if !statusBar.isRunning { return } - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + statusBar.interval) { - self.animate() - } - } + let cpu = CPU() + let statusBar = StatusBar() + let menuBarView = MenuBarView() + + func buttonInit() { + buttonImageChange("box") + menuBarView.buttonAppear(statusBar) + } + + func startRunning() { + statusBar.isRunning = cpu.processCPU(statusBar) + animate() + } + + func stopRunning() { + statusBar.isRunning = cpu.StopCPU() + } + + func animate() { + statusBar.statusItem.button?.image = statusBar.frames[statusBar.cnt] + statusBar.cnt = (statusBar.cnt + 1) % statusBar.frames.count + if !statusBar.isRunning { return } + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + statusBar.interval) { + self.animate() + } + } + + func buttonImageChange(_ img: String) { + menuBarView.imageChange("box", statusBar) + } } diff --git a/Box42/Menubar/MenubarModel.swift b/Box42/Menubar/MenubarModel.swift index 2daec9a..0a223f5 100644 --- a/Box42/Menubar/MenubarModel.swift +++ b/Box42/Menubar/MenubarModel.swift @@ -8,12 +8,10 @@ import AppKit public class StatusBar { - var statusItem = NSStatusItem() - var frames = [NSImage]() - var cnt: Int = 0 - var isRunning: Bool = false - var interval: Double = 1.0 - var alertCount: Int = 0 + var statusItem = NSStatusItem() + var frames = [NSImage]() + var cnt: Int = 0 + var isRunning: Bool = false + var interval: Double = 1.0 + var alertCount: Int = 0 } - - diff --git a/Box42/Menubar/MenubarView.swift b/Box42/Menubar/MenubarView.swift index e204aab..8f69493 100644 --- a/Box42/Menubar/MenubarView.swift +++ b/Box42/Menubar/MenubarView.swift @@ -9,23 +9,24 @@ import Foundation import AppKit class MenuBarView { - - func buttonAppear(_ statusBar: StatusBar) { - let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) - - statusBar.statusItem = statusItem - } - - func imageInit(_ imgName: String, _ statusBar: StatusBar) { - switch imgName { - 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 "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "lee_\(i)"))} - case "gam": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gam_\(i)"))} - case "box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(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)"))} - } - } + + func buttonAppear(_ statusBar: StatusBar) { + let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + + statusBar.statusItem = statusItem + } + + func imageChange(_ imgName: String, _ statusBar: StatusBar) { + statusBar.frames.removeAll() + switch imgName { + 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 "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "lee_\(i)"))} + case "gam": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gam_\(i)"))} + case "box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(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/Icon.swift b/Box42/Preferences/Icon.swift new file mode 100644 index 0000000..faca984 --- /dev/null +++ b/Box42/Preferences/Icon.swift @@ -0,0 +1,8 @@ +// +// Icon.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +import Foundation diff --git a/Box42/Resource/AppDelegate.swift b/Box42/Resource/AppDelegate.swift deleted file mode 100644 index c1c6cbd..0000000 --- a/Box42/Resource/AppDelegate.swift +++ /dev/null @@ -1,173 +0,0 @@ -// -// AppDelegate.swift -// Box42 -// -// Created by Chan on 2023/03/15. -// - -import Cocoa - -@main -class AppDelegate: NSObject, NSApplicationDelegate { - let popover = NSPopover() - var eventMonitor: EventMonitor? - var menubarController = MenuBarController() - var boxController = BoxController() - var boxStatus = BoxStatus() - - func applicationWillFinishLaunching(_ notification: Notification) { - menubarController.buttonInit() - } - - func applicationDidFinishLaunching(_ aNotification: Notification) { - menubarController.startRunning() - buttonActionInit() - popoverHandler() - eventMonitorHandler() - } - - func popoverHandler() { - popover.contentViewController = BoxController.freshController() - } - - func buttonActionInit() { - menubarController.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) - } - - func eventMonitorHandler() { - eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in - if let strongSelf = self, strongSelf.popover.isShown { - if self?.boxStatus.isPin == false { - strongSelf.closePopover(sender: event) - } - } - } - } - - @objc func togglePopover(_ sender: Any?) { - if popover.isShown { - closePopover(sender: sender) - } else { - showPopover(sender: sender) - } - } - - func showPopover(sender: Any?) { - if let button = menubarController.statusBar.statusItem.button { - popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) - } - eventMonitor?.start() - } - - func closePopover(sender: Any?) { - popover.performClose(sender) - eventMonitor?.stop() - } - - 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/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents b/Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents deleted file mode 100644 index e9aeffa..0000000 --- a/Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Box42/Resource/EventMonitor.swift b/Box42/Resource/EventMonitor.swift deleted file mode 100644 index 5051c36..0000000 --- a/Box42/Resource/EventMonitor.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// EventMonitor.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Cocoa - -public class EventMonitor { - private var monitor: Any? - private let mask: NSEvent.EventTypeMask - private let handler: (NSEvent?) -> Void - - public init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { - self.mask = mask - self.handler = handler - } - - deinit { - stop() - } - - public func start() { - monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) - } - - public func stop() { - if monitor != nil { - NSEvent.removeMonitor(monitor!) - monitor = nil - } - } -} diff --git a/Box42/Resource/Info.plist b/Box42/Resource/Info.plist deleted file mode 100644 index 6a6654d..0000000 --- a/Box42/Resource/Info.plist +++ /dev/null @@ -1,11 +0,0 @@ - - - - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - - diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift new file mode 100644 index 0000000..4ab862a --- /dev/null +++ b/Box42/Resources/AppDelegate.swift @@ -0,0 +1,173 @@ +// +// AppDelegate.swift +// Box42 +// +// Created by Chan on 2023/03/15. +// + +import Cocoa + +@main +class AppDelegate: NSObject, NSApplicationDelegate { + let popover = NSPopover() + var eventMonitor: EventMonitor? + var menubarController = MenuBarController() + var boxController = BoxController() + var boxStatus = BoxStatus() + + func applicationWillFinishLaunching(_ notification: Notification) { + menubarController.buttonInit() + } + + func applicationDidFinishLaunching(_ aNotification: Notification) { + menubarController.startRunning() + buttonActionInit() + popoverHandler() + eventMonitorHandler() + } + + func popoverHandler() { + popover.contentViewController = BoxController.freshController() + } + + func buttonActionInit() { + menubarController.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) + } + + func eventMonitorHandler() { + eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in + if let strongSelf = self, strongSelf.popover.isShown { + if self?.boxStatus.isPin == false { + strongSelf.closePopover(sender: event) + } + } + } + } + + @objc func togglePopover(_ sender: Any?) { + if popover.isShown { + closePopover(sender: sender) + } else { + showPopover(sender: sender) + } + } + + func showPopover(sender: Any?) { + if let button = menubarController.statusBar.statusItem.button { + popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) + } + eventMonitor?.start() + } + + func closePopover(sender: Any?) { + popover.performClose(sender) + eventMonitor?.stop() + } + + 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/Resource/Assets.xcassets/42box3/42box_1.imageset/42box_1.png b/Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/42box_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/42box_1.png rename to Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/42box_1.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/42box_2.png b/Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/42box_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/42box_2.png rename to Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/42box_2.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/42box_3.png b/Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/42box_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/42box_3.png rename to Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/42box_3.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/42box_4.png b/Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/42box_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/42box_4.png rename to Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/42box_4.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/Contents.json b/Box42/Resources/Assets.xcassets/42box3/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg b/Box42/Resources/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg rename to Box42/Resources/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg diff --git a/Box42/Resource/Assets.xcassets/42box_logo 1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_logo 1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo 1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_logo 1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_logo.imageset/42box_logo.png b/Box42/Resources/Assets.xcassets/42box_logo.imageset/42box_logo.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo.imageset/42box_logo.png rename to Box42/Resources/Assets.xcassets/42box_logo.imageset/42box_logo.png diff --git a/Box42/Resource/Assets.xcassets/42box_logo.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_logo.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_logo.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png b/Box42/Resources/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png rename to Box42/Resources/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png diff --git a/Box42/Resource/Assets.xcassets/42box_oc1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_oc1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_oc1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png b/Box42/Resources/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png rename to Box42/Resources/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png diff --git a/Box42/Resource/Assets.xcassets/42box_oc2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_oc2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_oc2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png diff --git a/Box42/Resource/Assets.xcassets/AccentColor.colorset/Contents.json b/Box42/Resources/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AccentColor.colorset/Contents.json rename to Box42/Resources/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/1024.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/1024.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/1024.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/1024.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/128.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/128.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/128.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/128.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/16.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/16.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/16.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/16.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/256.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/256.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/256.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/256.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/32.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/32.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/32.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/32.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/512.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/512.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/512.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/512.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/64.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/64.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/64.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/64.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/appstore.png b/Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/appstore.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/appstore.png rename to Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/appstore.png diff --git a/Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/playstore.png b/Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/playstore.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/playstore.png rename to Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/playstore.png diff --git a/Box42/Resource/Assets.xcassets/Contents.json b/Box42/Resources/Assets.xcassets/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/Contents.json rename to Box42/Resources/Assets.xcassets/Contents.json diff --git a/Box42/Resource/Box42.entitlements b/Box42/Resources/Box42.entitlements similarity index 100% rename from Box42/Resource/Box42.entitlements rename to Box42/Resources/Box42.entitlements diff --git a/Box42/Resource/Box42.xcdatamodeld/.xccurrentversion b/Box42/Resources/Box42.xcdatamodeld/.xccurrentversion similarity index 100% rename from Box42/Resource/Box42.xcdatamodeld/.xccurrentversion rename to Box42/Resources/Box42.xcdatamodeld/.xccurrentversion diff --git a/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents b/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents new file mode 100644 index 0000000..50d2514 --- /dev/null +++ b/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Box42/Resources/EventMonitor.swift b/Box42/Resources/EventMonitor.swift new file mode 100644 index 0000000..9f0087f --- /dev/null +++ b/Box42/Resources/EventMonitor.swift @@ -0,0 +1,34 @@ +// +// EventMonitor.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import Cocoa + +public class EventMonitor { + private var monitor: Any? + private let mask: NSEvent.EventTypeMask + private let handler: (NSEvent?) -> Void + + public init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { + self.mask = mask + self.handler = handler + } + + deinit { + stop() + } + + public func start() { + monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) + } + + public func stop() { + if monitor != nil { + NSEvent.removeMonitor(monitor!) + monitor = nil + } + } +} diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist new file mode 100644 index 0000000..a6a98a7 --- /dev/null +++ b/Box42/Resources/Info.plist @@ -0,0 +1,32 @@ + + + + + LSUIElement + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Box42/Resource/Main.storyboard b/Box42/Resources/Main.storyboard similarity index 71% rename from Box42/Resource/Main.storyboard rename to Box42/Resources/Main.storyboard index 0a27a60..dbd2ec4 100644 --- a/Box42/Resource/Main.storyboard +++ b/Box42/Resources/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -173,55 +173,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + diff --git a/Box42/Resources/StringExtension.swift b/Box42/Resources/StringExtension.swift new file mode 100644 index 0000000..fd1f378 --- /dev/null +++ b/Box42/Resources/StringExtension.swift @@ -0,0 +1,21 @@ +// +// StringExtension.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +import Foundation + +extension String { + var escapedForJavaScript: String { + let allowedCharacters = CharacterSet(charactersIn: "\"\\") + return self.unicodeScalars.map { char -> String in + if allowedCharacters.contains(char) { + return String(char) + } else { + return String(format: "\\u%04x", char.value) + } + }.joined() + } +} diff --git a/Box42/URL/URLModel.swift b/Box42/URL/URLModel.swift index f7a5c13..209828e 100644 --- a/Box42/URL/URLModel.swift +++ b/Box42/URL/URLModel.swift @@ -8,29 +8,31 @@ import Foundation struct URLModel { - let URLdict: [String: URL] = [ - "home": URL(string: "https://42box.github.io/front-end/")!, - "Box 42": URL(string: "https://42box.github.io/front-end/#/box")!, - "Intra 42": URL(string: "https://intra.42.fr")!, - "Jiphyeonjeon" : URL(string:"https://42library.kr")!, - "E-Library": URL(string:"https://42seoul.dkyobobook.co.kr/main.ink")!, - "24Hane": URL(string:"https://24hoursarenotenough.42seoul.kr")!, - "80000Coding": URL(string:"https://80000coding.oopy.io")!, - "where42": URL(string:"https://www.where42.kr")!, - "cabi": URL(string:"https://cabi.42seoul.io/")!, - "42gg": URL(string:"https://42gg.kr/")!, - ] - - let URLstring: [(String, String)] = [ - ("home", "https://42box.github.io/front-end/"), - ("Box 42", "https://42box.github.io/front-end/#/box"), - ("Intra 42", "https://intra.42.fr"), - ("Jiphyeonjeon", "https://42library.kr"), - ("E-Library", "https://42seoul.dkyobobook.co.kr/main.ink"), - ("24Hane", "https://24hoursarenotenough.42seoul.kr"), - ("80000Coding", "https://80000coding.oopy.io"), - ("where42", "https://www.where42.kr"), - ("cabi", "https://cabi.42seoul.io/"), - ("42gg", "https://42gg.kr/"), - ] + let URLdict: [String: URL] = [ + "home": URL(string: "https://42box.github.io/front-end/")!, + // "home": URL(string: "http://127.0.0.1:3000/")!, + "Box 42": URL(string: "https://42box.github.io/front-end/#/box")!, + "Intra 42": URL(string: "https://intra.42.fr")!, + "Jiphyeonjeon" : URL(string:"https://42library.kr")!, + "E-Library": URL(string:"https://42seoul.dkyobobook.co.kr/main.ink")!, + "24Hane": URL(string:"https://24hoursarenotenough.42seoul.kr")!, + "80000Coding": URL(string:"https://80000coding.oopy.io")!, + "where42": URL(string:"https://www.where42.kr")!, + "cabi": URL(string:"https://cabi.42seoul.io/")!, + "42gg": URL(string:"https://42gg.kr/")!, + ] + + let URLstring: [(String, String)] = [ + ("home", "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"), + ("E-Library", "https://42seoul.dkyobobook.co.kr/main.ink"), + ("24Hane", "https://24hoursarenotenough.42seoul.kr"), + ("80000Coding", "https://80000coding.oopy.io"), + ("where42", "https://www.where42.kr"), + ("cabi", "https://cabi.42seoul.io/"), + ("42gg", "https://42gg.kr/"), + ] } diff --git a/Box42/Web/WebViewController.swift b/Box42/Web/WebViewController.swift deleted file mode 100644 index f94f401..0000000 --- a/Box42/Web/WebViewController.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// WebViewController.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Cocoa -import WebKit - -class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - - func loadWebViewInit() { - for i in 0.. WKWebView { - let preferences = WKPreferences() - preferences.javaScriptEnabled = true - preferences.javaScriptCanOpenWindowsAutomatically = true - - let contentController = WKUserContentController() - contentController.add(self, name: "box") - - let configuration = WKWebViewConfiguration() - configuration.preferences = preferences - configuration.userContentController = contentController - - let webView = WKWebView(frame: .zero, configuration: configuration) - - webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true - webView.configuration.preferences.javaScriptEnabled = true - - webView.uiDelegate = self - webView.navigationDelegate = self - return webView - } - - override func viewDidLoad() { - super.viewDidLoad() - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - print(message.name) - } -} diff --git a/Box42/Web/WebViewModel.swift b/Box42/Web/WebViewModel.swift deleted file mode 100644 index 50f955f..0000000 --- a/Box42/Web/WebViewModel.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// WebViewModel.swift -// Box42 -// -// Created by Chan on 2023/03/19. -// - -import WebKit - -// Singleton -class WebViewList { - static let shared = WebViewList() - - var list: [String : WKWebView]! - - private init() { - list = [:] - } - -} diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift new file mode 100644 index 0000000..43b9033 --- /dev/null +++ b/Box42/WebView/WebViewController.swift @@ -0,0 +1,58 @@ +// +// WebViewController.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import Cocoa +import WebKit + +class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { + + func loadWebViewInit() { + for i in 0.. WKWebView { + let preferences = WKPreferences() + preferences.javaScriptEnabled = true + preferences.javaScriptCanOpenWindowsAutomatically = true + + let contentController = WKUserContentController() + contentController.add(self, name: "box") + + let configuration = WKWebViewConfiguration() + configuration.preferences = preferences + configuration.userContentController = contentController + + let webView = WKWebView(frame: .zero, configuration: configuration) + + webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true + webView.configuration.preferences.javaScriptEnabled = true + + webView.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") + if #available(macOS 11.0, *) { + webView.configuration.defaultWebpagePreferences.allowsContentJavaScript = true + } + + webView.uiDelegate = self + webView.navigationDelegate = self + return webView + } + + override func viewDidLoad() { + super.viewDidLoad() + } + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + print(message.name) + } +} diff --git a/Box42/WebView/WebViewModel.swift b/Box42/WebView/WebViewModel.swift new file mode 100644 index 0000000..162069a --- /dev/null +++ b/Box42/WebView/WebViewModel.swift @@ -0,0 +1,19 @@ +// +// WebViewModel.swift +// Box42 +// +// Created by Chan on 2023/03/19. +// + +import WebKit + +// Singleton +class WebViewList { + static let shared = WebViewList() + + var list: [String : WKWebView]! + + private init() { + list = [:] + } +} From e8584d144fb764b0760ec8a6bdb175f30ce3f243 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 9 Aug 2023 00:07:18 +0900 Subject: [PATCH 02/55] =?UTF-8?q?refactor(CleanUp=F0=9F=A7=B9):=20Resource?= =?UTF-8?q?s=20=ED=8F=B4=EB=8D=94=EB=A5=BC=20=EC=A0=95=EB=A6=AC=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box42.xcdatamodel/contents | 4 -- Box42/Resource/Info.plist | 11 ---- .../{Resource => Resources}/AppDelegate.swift | 53 ++---------------- .../42box3/42box_1.imageset/42box_1.png | Bin .../42box3/42box_1.imageset/Contents.json | 0 .../42box3/42box_2.imageset/42box_2.png | Bin .../42box3/42box_2.imageset/Contents.json | 0 .../42box3/42box_3.imageset/42box_3.png | Bin .../42box3/42box_3.imageset/Contents.json | 0 .../42box3/42box_4.imageset/42box_4.png | Bin .../42box3/42box_4.imageset/Contents.json | 0 .../Assets.xcassets/42box3/Contents.json | 0 .../42box_logo 1.imageset/42box_logo.svg | 0 .../42box_logo 1.imageset/Contents.json | 0 .../42box_logo.imageset/42box_logo.png | Bin .../42box_logo.imageset/Contents.json | 0 .../42box_oc1.imageset/42box_opend_black.png | Bin .../42box_oc1.imageset/Contents.json | 0 .../42box_oc2.imageset/42box_closed_black.png | Bin .../42box_oc2.imageset/Contents.json | 0 .../42flip/42flip_01.imageset/42flip_01.png | Bin .../42flip/42flip_01.imageset/Contents.json | 0 .../42flip/42flip_010.imageset/42flip_010.png | Bin .../42flip/42flip_010.imageset/Contents.json | 0 .../42flip/42flip_011.imageset/42flip_011.png | Bin .../42flip/42flip_011.imageset/Contents.json | 0 .../42flip/42flip_02.imageset/42flip_02.png | Bin .../42flip/42flip_02.imageset/Contents.json | 0 .../42flip/42flip_03.imageset/42flip_03.png | Bin .../42flip/42flip_03.imageset/Contents.json | 0 .../42flip/42flip_04.imageset/42flip_04.png | Bin .../42flip/42flip_04.imageset/Contents.json | 0 .../42flip/42flip_05.imageset/42flip_05.png | Bin .../42flip/42flip_05.imageset/Contents.json | 0 .../42flip/42flip_06.imageset/42flip_06.png | Bin .../42flip/42flip_06.imageset/Contents.json | 0 .../42flip/42flip_07.imageset/42flip_07.png | Bin .../42flip/42flip_07.imageset/Contents.json | 0 .../42flip/42flip_08.imageset/42flip_08.png | Bin .../42flip/42flip_08.imageset/Contents.json | 0 .../42flip/42flip_09.imageset/42flip_09.png | Bin .../42flip/42flip_09.imageset/Contents.json | 0 .../42pack_icon/42flip/42flip/Contents.json | 0 .../42pack_icon/42flip/Contents.json | 0 .../Assets.xcassets/42pack_icon/Contents.json | 0 .../42pack_icon/cat/Contents.json | 0 .../cat/cat_page0.imageset/Contents.json | 0 .../cat/cat_page0.imageset/cat0.png | Bin .../cat/cat_page1.imageset/Contents.json | 0 .../cat/cat_page1.imageset/cat1.png | Bin .../cat/cat_page2.imageset/Contents.json | 0 .../cat/cat_page2.imageset/cat2.png | Bin .../cat/cat_page3.imageset/Contents.json | 0 .../cat/cat_page3.imageset/cat3.png | Bin .../cat/cat_page4.imageset/Contents.json | 0 .../cat/cat_page4.imageset/cat4.png | Bin .../42pack_icon/gam/Contents.json | 0 .../gam/gam_1.imageset/Contents.json | 0 .../42pack_icon/gam/gam_1.imageset/gam_1.png | Bin .../gam/gam_2.imageset/Contents.json | 0 .../42pack_icon/gam/gam_2.imageset/gam_2.png | Bin .../gam/gam_3.imageset/Contents.json | 0 .../42pack_icon/gam/gam_3.imageset/gam_3.png | Bin .../gam/gam_4.imageset/Contents.json | 0 .../42pack_icon/gam/gam_4.imageset/gam_4.png | Bin .../gam/gam_5.imageset/Contents.json | 0 .../42pack_icon/gam/gam_5.imageset/gam_5.png | Bin .../42pack_icon/gon/Contents.json | 0 .../gon/gon_1.imageset/Contents.json | 0 .../42pack_icon/gon/gon_1.imageset/gon_1.png | Bin .../gon/gon_2.imageset/Contents.json | 0 .../42pack_icon/gon/gon_2.imageset/gon_2.png | Bin .../gon/gon_3.imageset/Contents.json | 0 .../42pack_icon/gon/gon_3.imageset/gon_3.png | Bin .../gon/gon_4.imageset/Contents.json | 0 .../42pack_icon/gon/gon_4.imageset/gon_4.png | Bin .../gon/gon_5.imageset/Contents.json | 0 .../42pack_icon/gon/gon_5.imageset/gon_5.png | Bin .../42pack_icon/gun/Contents.json | 0 .../gun/gun_1.imageset/Contents.json | 0 .../42pack_icon/gun/gun_1.imageset/gun_1.png | Bin .../gun/gun_2.imageset/Contents.json | 0 .../42pack_icon/gun/gun_2.imageset/gun_2.png | Bin .../gun/gun_3.imageset/Contents.json | 0 .../42pack_icon/gun/gun_3.imageset/gun_3.png | Bin .../gun/gun_4.imageset/Contents.json | 0 .../42pack_icon/gun/gun_4.imageset/gun_4.png | Bin .../gun/gun_5.imageset/Contents.json | 0 .../42pack_icon/gun/gun_5.imageset/gun_5.png | Bin .../42pack_icon/lee/Contents.json | 0 .../lee/lee_1.imageset/Contents.json | 0 .../42pack_icon/lee/lee_1.imageset/lee_1.png | Bin .../lee/lee_2.imageset/Contents.json | 0 .../42pack_icon/lee/lee_2.imageset/lee_2.png | Bin .../lee/lee_3.imageset/Contents.json | 0 .../42pack_icon/lee/lee_3.imageset/lee_3.png | Bin .../lee/lee_4.imageset/Contents.json | 0 .../42pack_icon/lee/lee_4.imageset/lee_4.png | Bin .../lee/lee_5.imageset/Contents.json | 0 .../42pack_icon/lee/lee_5.imageset/lee_5.png | Bin .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/1024.png | Bin .../AppIcon.appiconset/128.png | Bin .../Assets.xcassets/AppIcon.appiconset/16.png | Bin .../AppIcon.appiconset/256.png | Bin .../Assets.xcassets/AppIcon.appiconset/32.png | Bin .../AppIcon.appiconset/512.png | Bin .../Assets.xcassets/AppIcon.appiconset/64.png | Bin .../AppIcon.appiconset/Contents.json | 0 .../Assets.xcassets/AppIcons/Contents.json | 0 .../AppIcons/appstore.imageset/Contents.json | 0 .../AppIcons/appstore.imageset/appstore.png | Bin .../AppIcons/playstore.imageset/Contents.json | 0 .../AppIcons/playstore.imageset/playstore.png | Bin .../Assets.xcassets/Contents.json | 0 .../Box42.entitlements | 0 .../Box42.xcdatamodeld/.xccurrentversion | 0 .../Box42.xcdatamodel/contents | 4 ++ .../EventMonitor.swift | 4 +- Box42/Resources/Info.plist | 32 +++++++++++ Box42/{Resource => Resources}/Main.storyboard | 53 +++++++++--------- Box42/Resources/StringExtension.swift | 21 +++++++ 122 files changed, 92 insertions(+), 90 deletions(-) delete mode 100644 Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents delete mode 100644 Box42/Resource/Info.plist rename Box42/{Resource => Resources}/AppDelegate.swift (79%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_1.imageset/42box_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_2.imageset/42box_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_3.imageset/42box_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_4.imageset/42box_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/42box_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box3/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo 1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo.imageset/42box_logo.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_logo.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42box_oc2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/42flip/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/1024.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/128.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/16.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/256.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/32.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/512.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/64.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/appstore.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/appstore.imageset/appstore.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/playstore.imageset/Contents.json (100%) rename Box42/{Resource => Resources}/Assets.xcassets/AppIcons/playstore.imageset/playstore.png (100%) rename Box42/{Resource => Resources}/Assets.xcassets/Contents.json (100%) rename Box42/{Resource => Resources}/Box42.entitlements (100%) rename Box42/{Resource => Resources}/Box42.xcdatamodeld/.xccurrentversion (100%) create mode 100644 Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents rename Box42/{Resource => Resources}/EventMonitor.swift (88%) create mode 100644 Box42/Resources/Info.plist rename Box42/{Resource => Resources}/Main.storyboard (88%) create mode 100644 Box42/Resources/StringExtension.swift diff --git a/Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents b/Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents deleted file mode 100644 index e9aeffa..0000000 --- a/Box42/Resource/Box42.xcdatamodeld/Box42.xcdatamodel/contents +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Box42/Resource/Info.plist b/Box42/Resource/Info.plist deleted file mode 100644 index 6a6654d..0000000 --- a/Box42/Resource/Info.plist +++ /dev/null @@ -1,11 +0,0 @@ - - - - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - - diff --git a/Box42/Resource/AppDelegate.swift b/Box42/Resources/AppDelegate.swift similarity index 79% rename from Box42/Resource/AppDelegate.swift rename to Box42/Resources/AppDelegate.swift index c1c6cbd..5eaba15 100644 --- a/Box42/Resource/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -9,59 +9,16 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { - let popover = NSPopover() - var eventMonitor: EventMonitor? - var menubarController = MenuBarController() - var boxController = BoxController() - var boxStatus = BoxStatus() + var menubarController = MenubarViewController() func applicationWillFinishLaunching(_ notification: Notification) { - menubarController.buttonInit() + menubarController.menubarViewControllerInit() } func applicationDidFinishLaunching(_ aNotification: Notification) { - menubarController.startRunning() - buttonActionInit() - popoverHandler() - eventMonitorHandler() - } - - func popoverHandler() { - popover.contentViewController = BoxController.freshController() - } - - func buttonActionInit() { - menubarController.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) - } - - func eventMonitorHandler() { - eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in - if let strongSelf = self, strongSelf.popover.isShown { - if self?.boxStatus.isPin == false { - strongSelf.closePopover(sender: event) - } - } - } - } - - @objc func togglePopover(_ sender: Any?) { - if popover.isShown { - closePopover(sender: sender) - } else { - showPopover(sender: sender) - } - } - - func showPopover(sender: Any?) { - if let button = menubarController.statusBar.statusItem.button { - popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) - } - eventMonitor?.start() - } - - func closePopover(sender: Any?) { - popover.performClose(sender) - eventMonitor?.stop() + menubarController.menubarViewControllerStart() +// alertAccessibility() +// hotkey() } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/42box_1.png b/Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/42box_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/42box_1.png rename to Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/42box_1.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/42box_2.png b/Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/42box_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/42box_2.png rename to Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/42box_2.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/42box_3.png b/Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/42box_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/42box_3.png rename to Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/42box_3.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/42box_4.png b/Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/42box_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/42box_4.png rename to Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/42box_4.png diff --git a/Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/42box_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/42box_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box3/Contents.json b/Box42/Resources/Assets.xcassets/42box3/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box3/Contents.json rename to Box42/Resources/Assets.xcassets/42box3/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg b/Box42/Resources/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg rename to Box42/Resources/Assets.xcassets/42box_logo 1.imageset/42box_logo.svg diff --git a/Box42/Resource/Assets.xcassets/42box_logo 1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_logo 1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo 1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_logo 1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_logo.imageset/42box_logo.png b/Box42/Resources/Assets.xcassets/42box_logo.imageset/42box_logo.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo.imageset/42box_logo.png rename to Box42/Resources/Assets.xcassets/42box_logo.imageset/42box_logo.png diff --git a/Box42/Resource/Assets.xcassets/42box_logo.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_logo.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_logo.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_logo.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png b/Box42/Resources/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png rename to Box42/Resources/Assets.xcassets/42box_oc1.imageset/42box_opend_black.png diff --git a/Box42/Resource/Assets.xcassets/42box_oc1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_oc1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_oc1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png b/Box42/Resources/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png rename to Box42/Resources/Assets.xcassets/42box_oc2.imageset/42box_closed_black.png diff --git a/Box42/Resource/Assets.xcassets/42box_oc2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42box_oc2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42box_oc2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42box_oc2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/42flip_01.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_01.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/42flip_010.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_010.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/42flip_011.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_011.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/42flip_02.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_02.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/42flip_03.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_03.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/42flip_04.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_04.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/42flip_05.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_05.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/42flip_06.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_06.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/42flip_07.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_07.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/42flip_08.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_08.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/42flip_09.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/42flip_09.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/42flip/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/42flip/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/42flip/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/42flip/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/42flip/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page0.imageset/cat0.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page1.imageset/cat1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page2.imageset/cat2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page3.imageset/cat3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png b/Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/cat/cat_page4.imageset/cat4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_1.imageset/gam_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_2.imageset/gam_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_3.imageset/gam_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_4.imageset/gam_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gam/gam_5.imageset/gam_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_1.imageset/gon_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_2.imageset/gon_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_3.imageset/gon_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_4.imageset/gon_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gon/gon_5.imageset/gon_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_1.imageset/gun_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_2.imageset/gun_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_3.imageset/gun_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_4.imageset/gun_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/gun/gun_5.imageset/gun_5.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_1.imageset/lee_1.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_2.imageset/lee_2.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_3.imageset/lee_3.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_4.imageset/lee_4.png diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png b/Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png similarity index 100% rename from Box42/Resource/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png rename to Box42/Resources/Assets.xcassets/42pack_icon/lee/lee_5.imageset/lee_5.png diff --git a/Box42/Resource/Assets.xcassets/AccentColor.colorset/Contents.json b/Box42/Resources/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AccentColor.colorset/Contents.json rename to Box42/Resources/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/1024.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/1024.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/1024.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/1024.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/128.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/128.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/128.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/128.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/16.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/16.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/16.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/16.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/256.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/256.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/256.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/256.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/32.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/32.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/32.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/32.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/512.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/512.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/512.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/512.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/64.png b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/64.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/64.png rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/64.png diff --git a/Box42/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/appstore.png b/Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/appstore.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/appstore.imageset/appstore.png rename to Box42/Resources/Assets.xcassets/AppIcons/appstore.imageset/appstore.png diff --git a/Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/Contents.json b/Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/Contents.json rename to Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/Contents.json diff --git a/Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/playstore.png b/Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/playstore.png similarity index 100% rename from Box42/Resource/Assets.xcassets/AppIcons/playstore.imageset/playstore.png rename to Box42/Resources/Assets.xcassets/AppIcons/playstore.imageset/playstore.png diff --git a/Box42/Resource/Assets.xcassets/Contents.json b/Box42/Resources/Assets.xcassets/Contents.json similarity index 100% rename from Box42/Resource/Assets.xcassets/Contents.json rename to Box42/Resources/Assets.xcassets/Contents.json diff --git a/Box42/Resource/Box42.entitlements b/Box42/Resources/Box42.entitlements similarity index 100% rename from Box42/Resource/Box42.entitlements rename to Box42/Resources/Box42.entitlements diff --git a/Box42/Resource/Box42.xcdatamodeld/.xccurrentversion b/Box42/Resources/Box42.xcdatamodeld/.xccurrentversion similarity index 100% rename from Box42/Resource/Box42.xcdatamodeld/.xccurrentversion rename to Box42/Resources/Box42.xcdatamodeld/.xccurrentversion diff --git a/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents b/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents new file mode 100644 index 0000000..50d2514 --- /dev/null +++ b/Box42/Resources/Box42.xcdatamodeld/Box42.xcdatamodel/contents @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Box42/Resource/EventMonitor.swift b/Box42/Resources/EventMonitor.swift similarity index 88% rename from Box42/Resource/EventMonitor.swift rename to Box42/Resources/EventMonitor.swift index 5051c36..ca7722b 100644 --- a/Box42/Resource/EventMonitor.swift +++ b/Box42/Resources/EventMonitor.swift @@ -16,17 +16,19 @@ public class EventMonitor { self.mask = mask self.handler = handler } - + deinit { stop() } public func start() { + print("EventMonitor: Starting") monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) } public func stop() { if monitor != nil { + print("EventMonitor: Stoping") NSEvent.removeMonitor(monitor!) monitor = nil } diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist new file mode 100644 index 0000000..a6a98a7 --- /dev/null +++ b/Box42/Resources/Info.plist @@ -0,0 +1,32 @@ + + + + + LSUIElement + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Box42/Resource/Main.storyboard b/Box42/Resources/Main.storyboard similarity index 88% rename from Box42/Resource/Main.storyboard rename to Box42/Resources/Main.storyboard index 0a27a60..7332997 100644 --- a/Box42/Resource/Main.storyboard +++ b/Box42/Resources/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -174,54 +174,55 @@ - + - - + + + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + diff --git a/Box42/Resources/StringExtension.swift b/Box42/Resources/StringExtension.swift new file mode 100644 index 0000000..fd1f378 --- /dev/null +++ b/Box42/Resources/StringExtension.swift @@ -0,0 +1,21 @@ +// +// StringExtension.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +import Foundation + +extension String { + var escapedForJavaScript: String { + let allowedCharacters = CharacterSet(charactersIn: "\"\\") + return self.unicodeScalars.map { char -> String in + if allowedCharacters.contains(char) { + return String(char) + } else { + return String(format: "\\u%04x", char.value) + } + }.joined() + } +} From 3d2a3724bd4eb00f3e1575ff30c422d456040410 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 9 Aug 2023 00:24:05 +0900 Subject: [PATCH 03/55] refactor(Remove): unnecessary files --- .prettierrc | 4 - .swift-format | 54 -- Box42.xcodeproj/project.pbxproj | 473 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../UserInterfaceState.xcuserstate | Bin 114504 -> 0 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 24 - .../xcschemes/xcschememanagement.plist | 14 - 8 files changed, 584 deletions(-) delete mode 100644 .prettierrc delete mode 100644 .swift-format delete mode 100644 Box42.xcodeproj/project.pbxproj delete mode 100644 Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist delete mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 222861c..0000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "tabWidth": 2, - "useTabs": false -} diff --git a/.swift-format b/.swift-format deleted file mode 100644 index df1fc72..0000000 --- a/.swift-format +++ /dev/null @@ -1,54 +0,0 @@ -{ - "fileScopedDeclarationPrivacy" : { - "accessLevel" : "private" - }, - "indentation" : { - "spaces" : 2 - }, - "indentConditionalCompilationBlocks" : true, - "indentSwitchCaseLabels" : false, - "lineBreakAroundMultilineExpressionChainComponents" : false, - "lineBreakBeforeControlFlowKeywords" : false, - "lineBreakBeforeEachArgument" : false, - "lineBreakBeforeEachGenericRequirement" : false, - "lineLength" : 100, - "maximumBlankLines" : 1, - "prioritizeKeepingFunctionOutputTogether" : false, - "respectsExistingLineBreaks" : true, - "rules" : { - "AllPublicDeclarationsHaveDocumentation" : false, - "AlwaysUseLowerCamelCase" : true, - "AmbiguousTrailingClosureOverload" : true, - "BeginDocumentationCommentWithOneLineSummary" : true, - "DoNotUseSemicolons" : true, - "DontRepeatTypeInStaticProperties" : true, - "FileScopedDeclarationPrivacy" : true, - "FullyIndirectEnum" : true, - "GroupNumericLiterals" : true, - "IdentifiersMustBeASCII" : true, - "NeverForceUnwrap" : false, - "NeverUseForceTry" : false, - "NeverUseImplicitlyUnwrappedOptionals" : false, - "NoAccessLevelOnExtensionDeclaration" : true, - "NoBlockComments" : true, - "NoCasesWithOnlyFallthrough" : true, - "NoEmptyTrailingClosureParentheses" : true, - "NoLabelsInCasePatterns" : true, - "NoLeadingUnderscores" : false, - "NoParensAroundConditions" : true, - "NoVoidReturnOnFunctionSignature" : true, - "OneCasePerLine" : true, - "OneVariableDeclarationPerLine" : true, - "OnlyOneTrailingClosureArgument" : true, - "OrderedImports" : true, - "ReturnVoidInsteadOfEmptyTuple" : true, - "UseLetInEveryBoundCaseVariable" : true, - "UseShorthandTypeNames" : true, - "UseSingleLinePropertyGetter" : true, - "UseSynthesizedInitializer" : true, - "UseTripleSlashForDocumentationComments" : true, - "ValidateDocumentationComments" : false - }, - "tabWidth" : 8, - "version" : 1 -} diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj deleted file mode 100644 index 26872ec..0000000 --- a/Box42.xcodeproj/project.pbxproj +++ /dev/null @@ -1,473 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */; }; - DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */; }; - DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */; }; - DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */; }; - DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE32A509B1700FF0AA3 /* CPU.swift */; }; - DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */; }; - DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */; }; - DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEC2A509B2600FF0AA3 /* URLModel.swift */; }; - DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */; }; - DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; - DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; - DE018BF92A509B3B00FF0AA3 /* BoxController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF82A509B3B00FF0AA3 /* BoxController.swift */; }; - DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */; }; - DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFE2A509B4200FF0AA3 /* BoxView.swift */; }; - DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; - DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; - DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; - DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; - DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesController.swift */; }; - 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 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - DE018BAF2A5099F900FF0AA3 /* Box42.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Box42.app; sourceTree = BUILT_PRODUCTS_DIR; }; - DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Box42.xcdatamodel; sourceTree = ""; }; - DE018BBE2A5099FA00FF0AA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; - DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - DE018BE32A509B1700FF0AA3 /* CPU.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = ""; }; - DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; - DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = ""; }; - DE018BEC2A509B2600FF0AA3 /* URLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLModel.swift; sourceTree = ""; }; - DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarViewController.swift; sourceTree = ""; }; - DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; - DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; - DE018BF82A509B3B00FF0AA3 /* BoxController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxController.swift; sourceTree = ""; }; - DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxModel.swift; sourceTree = ""; }; - DE018BFE2A509B4200FF0AA3 /* BoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; - DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; - DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; - DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.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 /* PreferencesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesController.swift; 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 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - DE018BAC2A5099F900FF0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - DE018BA62A5099F900FF0AA3 = { - isa = PBXGroup; - children = ( - DE018BB12A5099F900FF0AA3 /* Box42 */, - DE018BB02A5099F900FF0AA3 /* Products */, - ); - sourceTree = ""; - }; - DE018BB02A5099F900FF0AA3 /* Products */ = { - isa = PBXGroup; - children = ( - DE018BAF2A5099F900FF0AA3 /* Box42.app */, - ); - name = Products; - sourceTree = ""; - }; - DE018BB12A5099F900FF0AA3 /* Box42 */ = { - isa = PBXGroup; - children = ( - DE77BA542A82636500713683 /* Shared */, - DE874F512A591EC600FC3B77 /* Preferences */, - DE018C0C2A509BDF00FF0AA3 /* Resources */, - DE018C062A509B9000FF0AA3 /* CPU */, - DE018C082A509BB500FF0AA3 /* WebView */, - DE018C0B2A509BC100FF0AA3 /* URL */, - DE018C0E2A509C0C00FF0AA3 /* Menubar */, - DE018C102A509C1A00FF0AA3 /* Box */, - ); - path = Box42; - sourceTree = ""; - }; - DE018C062A509B9000FF0AA3 /* CPU */ = { - isa = PBXGroup; - children = ( - DE018BE32A509B1700FF0AA3 /* CPU.swift */, - ); - path = CPU; - sourceTree = ""; - }; - DE018C082A509BB500FF0AA3 /* WebView */ = { - isa = PBXGroup; - children = ( - DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, - DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, - ); - path = WebView; - sourceTree = ""; - }; - DE018C0B2A509BC100FF0AA3 /* URL */ = { - isa = PBXGroup; - children = ( - DE018BEC2A509B2600FF0AA3 /* URLModel.swift */, - ); - path = URL; - sourceTree = ""; - }; - DE018C0C2A509BDF00FF0AA3 /* Resources */ = { - isa = PBXGroup; - children = ( - DE018C192A509DBA00FF0AA3 /* Box42.entitlements */, - DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */, - DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, - DE018BBE2A5099FA00FF0AA3 /* Info.plist */, - DE018C022A509B5D00FF0AA3 /* Main.storyboard */, - DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, - DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */, - DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */, - ); - path = Resources; - sourceTree = ""; - }; - DE018C0E2A509C0C00FF0AA3 /* Menubar */ = { - isa = PBXGroup; - children = ( - DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */, - DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */, - DE018BF52A509B3600FF0AA3 /* MenubarView.swift */, - DE77BA502A82580400713683 /* MenubarViewModel.swift */, - ); - path = Menubar; - sourceTree = ""; - }; - DE018C102A509C1A00FF0AA3 /* Box */ = { - isa = PBXGroup; - children = ( - DE018BF82A509B3B00FF0AA3 /* BoxController.swift */, - DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */, - DE018BFE2A509B4200FF0AA3 /* BoxView.swift */, - ); - path = Box; - sourceTree = ""; - }; - DE77BA542A82636500713683 /* Shared */ = { - isa = PBXGroup; - children = ( - DE77BA552A82637900713683 /* StateManager.swift */, - ); - path = Shared; - sourceTree = ""; - }; - DE874F512A591EC600FC3B77 /* Preferences */ = { - isa = PBXGroup; - children = ( - DE7A25792A6D8CA20043225A /* PreferencesController.swift */, - DE874F532A591F1400FC3B77 /* PreferencesView.swift */, - DE874F562A591F2500FC3B77 /* Icon.swift */, - DE2AD3282A824EEB00002D51 /* Accessibility.swift */, - DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */, - ); - path = Preferences; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - DE018BAE2A5099F900FF0AA3 /* Box42 */ = { - isa = PBXNativeTarget; - buildConfigurationList = DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */; - buildPhases = ( - DE018BAB2A5099F900FF0AA3 /* Sources */, - DE018BAC2A5099F900FF0AA3 /* Frameworks */, - DE018BAD2A5099F900FF0AA3 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Box42; - productName = Box42; - productReference = DE018BAF2A5099F900FF0AA3 /* Box42.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - DE018BA72A5099F900FF0AA3 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1230; - LastUpgradeCheck = 1230; - TargetAttributes = { - DE018BAE2A5099F900FF0AA3 = { - CreatedOnToolsVersion = 12.3; - }; - }; - }; - buildConfigurationList = DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = DE018BA62A5099F900FF0AA3; - productRefGroup = DE018BB02A5099F900FF0AA3 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DE018BAE2A5099F900FF0AA3 /* Box42 */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - DE018BAD2A5099F900FF0AA3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */, - DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - DE018BAB2A5099F900FF0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */, - DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, - DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, - DE77BA562A82637900713683 /* StateManager.swift in Sources */, - DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, - DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, - DE018BF92A509B3B00FF0AA3 /* BoxController.swift in Sources */, - DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, - DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, - DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, - DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, - DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, - DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, - DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, - DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */, - DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, - DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */, - DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, - DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, - DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, - DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - DE018BC02A5099FA00FF0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - DE018BC12A5099FA00FF0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - DE018BC32A5099FA00FF0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = Box42/Box42.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Box42/Resources/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - DE018BC42A5099FA00FF0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = Box42/Box42.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Box42/Resources/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DE018BC02A5099FA00FF0AA3 /* Debug */, - DE018BC12A5099FA00FF0AA3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DE018BC32A5099FA00FF0AA3 /* Debug */, - DE018BC42A5099FA00FF0AA3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - -/* Begin XCVersionGroup section */ - DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */, - ); - currentVersion = DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */; - path = Box42.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; -/* End XCVersionGroup section */ - }; - rootObject = DE018BA72A5099F900FF0AA3 /* Project object */; -} diff --git a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index fc75f4fb0009991e79037615f5a429de9d2db645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114504 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 D7z7ru diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index e9d969f..0000000 --- a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2d4f387..0000000 --- a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - Box42.xcscheme_^#shared#^_ - - orderHint - 0 - - - - From c9f3505d745a785b9eb245c3f4bf6beeb7f406ad Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 9 Aug 2023 14:34:51 +0900 Subject: [PATCH 04/55] =?UTF-8?q?refactor(Architecture=F0=9F=8F=9B):=20MVC?= =?UTF-8?q?=20to=20MVVM=20in=20menubar=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/BoxModel.swift | 15 -- ...ntroller.swift => BoxViewController.swift} | 8 +- Box42/CPU/CPU.swift | 2 +- Box42/Menubar/MenubarViewController.swift | 6 +- Box42/Resources/AppDelegate.swift | 173 ------------------ Box42/Resources/EventMonitor.swift | 34 ---- 6 files changed, 7 insertions(+), 231 deletions(-) rename Box42/Box/{BoxController.swift => BoxViewController.swift} (97%) diff --git a/Box42/Box/BoxModel.swift b/Box42/Box/BoxModel.swift index b188c95..d6f114c 100644 --- a/Box42/Box/BoxModel.swift +++ b/Box42/Box/BoxModel.swift @@ -7,21 +7,6 @@ import WebKit -public extension NSScreen { - static let screenSize = NSScreen.main?.visibleFrame.size - static let screenWidth = screenSize!.width - static let screenHeight = screenSize!.height - static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) - static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) -} - -public struct BoxViewSize { - var halfSize: (width: CGFloat, height: CGFloat) = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) - var size: (width: CGFloat, height: CGFloat) = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) - var buttonGroupSize: (width: CGFloat, height: CGFloat) = (CGFloat(132), NSScreen.customScreenSize.y) - var viewStack = [NSView()] -} - public class BoxStatus { var isPin: Bool = false } diff --git a/Box42/Box/BoxController.swift b/Box42/Box/BoxViewController.swift similarity index 97% rename from Box42/Box/BoxController.swift rename to Box42/Box/BoxViewController.swift index 5d9cfc9..9d19ef9 100644 --- a/Box42/Box/BoxController.swift +++ b/Box42/Box/BoxViewController.swift @@ -9,7 +9,7 @@ import Cocoa import AppKit import WebKit -class BoxController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { +class BoxViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { var ad = NSApplication.shared.delegate as? AppDelegate let url = URLModel() var wvc = WebViewController() @@ -262,12 +262,12 @@ class BoxController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKN } } -extension BoxController { - static func freshController() -> BoxController { +extension BoxViewController { + static func freshController() -> BoxViewController { let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) let identifier = NSStoryboard.SceneIdentifier("BoxController") - guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxController else { + guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxViewController else { fatalError("Story Board Not Found") } return viewcontroller diff --git a/Box42/CPU/CPU.swift b/Box42/CPU/CPU.swift index 33c11a9..7f59495 100644 --- a/Box42/CPU/CPU.swift +++ b/Box42/CPU/CPU.swift @@ -54,7 +54,7 @@ public class CPU { return true } - public func processCPU(_ statusBar: StatusBar) -> Bool { + func processCPU(_ statusBar: StatusBar) -> Bool { 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 diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 032e463..7c29ca7 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -14,9 +14,7 @@ class MenubarViewController: NSWorkspace { lazy var eventMonitor: EventMonitor = self.setupEventMonitor() var statusBarVM: StatusBarViewModel? // 옵셔널로 선언 let menuBarView = MenuBarView() - lazy var keyboardEventMonitor = EventMonitor(mask: [.keyDown]) { [weak self] event in - print("keydown") - } + // 초기화 함수나 다른 적절한 시점에 호출 func initializeStatusBarVM() { statusBarVM = StatusBarViewModel(eventMonitor: eventMonitor) @@ -56,7 +54,7 @@ class MenubarViewController: NSWorkspace { } func popoverHandler() { - popover.contentViewController = BoxController.freshController() + popover.contentViewController = BoxViewController.freshController() } func setupEventMonitor() -> EventMonitor { diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 688a686..5eaba15 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -7,179 +7,6 @@ import Cocoa -@main -class AppDelegate: NSObject, NSApplicationDelegate { - let popover = NSPopover() - var eventMonitor: EventMonitor? - var menubarController = MenuBarController() - var boxController = BoxController() - var boxStatus = BoxStatus() - - func applicationWillFinishLaunching(_ notification: Notification) { - menubarController.buttonInit() - } - - func applicationDidFinishLaunching(_ aNotification: Notification) { - menubarController.startRunning() - buttonActionInit() - popoverHandler() - eventMonitorHandler() - } - - func popoverHandler() { - popover.contentViewController = BoxController.freshController() - } - - func buttonActionInit() { - menubarController.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) - } - - func eventMonitorHandler() { - eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in - if let strongSelf = self, strongSelf.popover.isShown { - if self?.boxStatus.isPin == false { - strongSelf.closePopover(sender: event) - } - } - } - } - - @objc func togglePopover(_ sender: Any?) { - if popover.isShown { - closePopover(sender: sender) - } else { - showPopover(sender: sender) - } - } - - func showPopover(sender: Any?) { - if let button = menubarController.statusBar.statusItem.button { - popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) - } - eventMonitor?.start() - } - - func closePopover(sender: Any?) { - popover.performClose(sender) - eventMonitor?.stop() - } - - 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 - } - -} - -// -// AppDelegate.swift -// Box42 -// -// Created by Chan on 2023/03/15. -// - -import Cocoa - @main class AppDelegate: NSObject, NSApplicationDelegate { var menubarController = MenubarViewController() diff --git a/Box42/Resources/EventMonitor.swift b/Box42/Resources/EventMonitor.swift index e56d895..ca7722b 100644 --- a/Box42/Resources/EventMonitor.swift +++ b/Box42/Resources/EventMonitor.swift @@ -7,40 +7,6 @@ import Cocoa -public class EventMonitor { - private var monitor: Any? - private let mask: NSEvent.EventTypeMask - private let handler: (NSEvent?) -> Void - - public init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { - self.mask = mask - self.handler = handler - } - - deinit { - stop() - } - - public func start() { - monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) - } - - public func stop() { - if monitor != nil { - NSEvent.removeMonitor(monitor!) - monitor = nil - } - } -} -// -// EventMonitor.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Cocoa - public class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask From e35df0e78fe98d75d4f836d8b6c12a68633708d7 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:10:00 +0900 Subject: [PATCH 05/55] =?UTF-8?q?docs:=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a8d29c..597f6e1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # macOS -[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2F42Box%2FmacOS%2Freleases&count_bg=%23E7D166&title_bg=%23EB7F40&icon=dropbox.svg&icon_color=%23E7E7E7&title=Download+Count&edge_flat=false)](https://hits.seeyoufarm.com) +[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2F42Box%2FmacOS%2Freleases&count_bg=%23E7D166&title_bg=%23EB7F40&icon=dropbox.svg&icon_color=%23E7E7E7&title=찾아와주셔서+감사합니다!&edge_flat=false)](https://hits.seeyoufarm.com) [v1.0.1 Beta Release Note](https://github.com/42Box/macOS/releases/tag/v1.0.1) From 13676b1f0ccfa039e4396a54e3eb949d2599c82b Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 11 Aug 2023 04:04:38 +0900 Subject: [PATCH 06/55] =?UTF-8?q?refactor:=20extension=EC=9D=98=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EA=B5=AC=EC=A1=B0=EB=A5=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Extensions/NSScreen.swift | 16 ++++++++++++++++ .../StringExtension.swift | 0 2 files changed, 16 insertions(+) create mode 100644 Box42/Extensions/NSScreen.swift rename Box42/{Resources => Extensions}/StringExtension.swift (100%) diff --git a/Box42/Extensions/NSScreen.swift b/Box42/Extensions/NSScreen.swift new file mode 100644 index 0000000..778e4fd --- /dev/null +++ b/Box42/Extensions/NSScreen.swift @@ -0,0 +1,16 @@ +// +// NSScreen.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +extension NSScreen { + static let screenSize = NSScreen.main?.visibleFrame.size + static let screenWidth = screenSize!.width + static let screenHeight = screenSize!.height + static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) + static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) +} diff --git a/Box42/Resources/StringExtension.swift b/Box42/Extensions/StringExtension.swift similarity index 100% rename from Box42/Resources/StringExtension.swift rename to Box42/Extensions/StringExtension.swift From e6cd5b0b77978c4a666a98cc14420868a7773740 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 11 Aug 2023 04:05:14 +0900 Subject: [PATCH 07/55] =?UTF-8?q?refactor:=20Menubar=EB=A5=BC=20mvc?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=EC=97=90=EC=84=9C=20mvvm=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=98=EC=98=80=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Menubar/MenubarModel.swift | 2 + Box42/Menubar/MenubarViewController.swift | 81 ++++++++++++++++------- Box42/Menubar/MenubarViewModel.swift | 37 ++++++++--- 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/Box42/Menubar/MenubarModel.swift b/Box42/Menubar/MenubarModel.swift index 4e920ba..24a9a73 100644 --- a/Box42/Menubar/MenubarModel.swift +++ b/Box42/Menubar/MenubarModel.swift @@ -8,6 +8,8 @@ import AppKit class StatusBar { + static let shared = StatusBar() + var statusItem: NSStatusItem var frames: [NSImage] var cnt: Int diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 7c29ca7..b381e1c 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -11,17 +11,13 @@ import AppKit class MenubarViewController: NSWorkspace { var popover = NSPopover() - lazy var eventMonitor: EventMonitor = self.setupEventMonitor() - var statusBarVM: StatusBarViewModel? // 옵셔널로 선언 + var statusBarVM = StatusBarViewModel() let menuBarView = MenuBarView() - - // 초기화 함수나 다른 적절한 시점에 호출 - func initializeStatusBarVM() { - statusBarVM = StatusBarViewModel(eventMonitor: eventMonitor) - } - + lazy var eventMonitor: EventMonitor = self.setupEventMonitor() + var boxWindowController: BoxWindowController? + + func menubarViewControllerInit() { - self.initializeStatusBarVM() self.buttonInit() } @@ -29,38 +25,43 @@ class MenubarViewController: NSWorkspace { self.menubarStartRunning() self.buttonActionInit() self.popoverHandler() + self.startEventMonitoring() + } + + func startEventMonitoring() { + eventMonitor.start() + } + + func stopEventMonitoring() { + eventMonitor.stop() } func menubarStartRunning() { - statusBarVM?.startRunning() + statusBarVM.startRunning() } func menubarStopRunning() { - statusBarVM?.stopRunning() + statusBarVM.stopRunning() } func buttonInit() { - buttonImageChange("box") - statusBarVM?.statusButtonAppear() + buttonImageChange("Cat") + statusBarVM.statusButtonAppear() } func buttonImageChange(_ img: String) { - statusBarVM?.changeStatusBarIcon(img) + statusBarVM.changeStatusBarIcon(img) } func buttonActionInit() { - statusBarVM?.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) - statusBarVM?.statusBar.statusItem.button?.target = self - } - - func popoverHandler() { - popover.contentViewController = BoxViewController.freshController() + statusBarVM.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) + statusBarVM.statusBar.statusItem.button?.target = self } func setupEventMonitor() -> EventMonitor { return EventMonitor(mask: [.leftMouseDown, .rightMouseDown, .otherMouseDown]) { [weak self] event in if let strongSelf = self, strongSelf.popover.isShown { - if StateManager.shared.isPin == false && event?.buttonNumber != 2 { + if StateManager.shared.getIsPin() == false && event?.buttonNumber != 2 { strongSelf.closePopover(sender: event) } } else if let strongSelf = self, !strongSelf.popover.isShown { @@ -79,15 +80,47 @@ class MenubarViewController: NSWorkspace { } } + func popoverHandler() { + popover.contentViewController = BoxViewController.freshController() + } + func showPopover(sender: Any?) { - if let button = statusBarVM?.statusBar.statusItem.button { + if let event = sender as? NSEvent { + if event.type == .otherMouseDown { + self.showWindow(sender: sender) + } + } else if let button = statusBarVM.statusBar.statusItem.button { popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) } - eventMonitor.start() } + + func showWindow(sender: Any?) { + boxWindowController?.close() + + boxWindowController = BoxWindowController(windowNibName: NSNib.Name("BoxWindowController")) + + // status bar 버튼의 위치를 얻어옵니다. + if let button = statusBarVM.statusBar.statusItem.button, + let screenFrame = NSScreen.main?.frame, + let window = boxWindowController?.window { + + let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect + + // 버튼 위치 아래에 윈도우를 표시하려면 + let desiredPosition = NSPoint(x: buttonFrame.origin.x, y: buttonFrame.origin.y - window.frame.height) + + // 혹은, 버튼 위치의 중앙에 윈도우를 표시하려면 +// let desiredPosition = NSPoint(x: buttonFrame.midX - window.frame.width / 2, y: buttonFrame.origin.y - window.frame.height) + + // 윈도우의 위치를 설정 + window.setFrameOrigin(desiredPosition) + } + boxWindowController?.contentViewController = BoxViewController.freshController() + boxWindowController?.showWindow(sender) + } + func closePopover(sender: Any?) { popover.performClose(sender) -// eventMonitor.stop() } } diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index 6f0b12c..d131b10 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -9,13 +9,12 @@ import AppKit class StatusBarViewModel { let cpu: CPU - let eventMonitor: EventMonitor let statusBar: StatusBar + private var currentAnimationWorkItem: DispatchWorkItem? - init (eventMonitor: EventMonitor) { - self.statusBar = StatusBar() + init () { + self.statusBar = StatusBar.shared self.cpu = CPU() - self.eventMonitor = eventMonitor } func statusButtonAppear() { @@ -24,12 +23,14 @@ class StatusBarViewModel { func changeStatusBarIcon(_ imgName: String) { 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 "lee": for i in (1...5) {statusBar.frames.append(NSImage(imageLiteralResourceName: "gam_\(i)"))} - case "box": for i in (1...4) {statusBar.frames.append(NSImage(imageLiteralResourceName: "42box_\(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_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)"))} } @@ -37,19 +38,39 @@ class StatusBarViewModel { func startRunning() { statusBar.isRunning = cpu.processCPU(statusBar) - self.animate() +// self.animate() + scheduleAnimation() } func animate() { statusBar.statusItem.button?.image = statusBar.frames[statusBar.cnt] statusBar.cnt = (statusBar.cnt + 1) % statusBar.frames.count if !statusBar.isRunning { return } + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + statusBar.interval) { self.animate() } } + func scheduleAnimation() { + currentAnimationWorkItem?.cancel() + + let workItem = DispatchWorkItem { [weak self] in + self?.statusBar.statusItem.button?.image = self?.statusBar.frames[self?.statusBar.cnt ?? 0] + self?.statusBar.cnt = ((self?.statusBar.cnt)! + 1) % (self?.statusBar.frames.count ?? 1) + + if self?.statusBar.isRunning ?? false { + self?.scheduleAnimation() + } + } + + currentAnimationWorkItem = workItem + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + statusBar.interval, execute: workItem) + } + func stopRunning() { statusBar.isRunning = cpu.StopCPU() + currentAnimationWorkItem?.cancel() + statusBar.cnt = 0 } } From dea779efdc475b7a567f4ace52be44262ffee5ef Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 11 Aug 2023 04:06:11 +0900 Subject: [PATCH 08/55] =?UTF-8?q?refactor:=20URLModel=EC=9D=84=20mvvm?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/URL/URLModel.swift | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/Box42/URL/URLModel.swift b/Box42/URL/URLModel.swift index 209828e..9763fce 100644 --- a/Box42/URL/URLModel.swift +++ b/Box42/URL/URLModel.swift @@ -8,20 +8,21 @@ import Foundation struct URLModel { - let URLdict: [String: URL] = [ - "home": URL(string: "https://42box.github.io/front-end/")!, - // "home": URL(string: "http://127.0.0.1:3000/")!, - "Box 42": URL(string: "https://42box.github.io/front-end/#/box")!, - "Intra 42": URL(string: "https://intra.42.fr")!, - "Jiphyeonjeon" : URL(string:"https://42library.kr")!, - "E-Library": URL(string:"https://42seoul.dkyobobook.co.kr/main.ink")!, - "24Hane": URL(string:"https://24hoursarenotenough.42seoul.kr")!, - "80000Coding": URL(string:"https://80000coding.oopy.io")!, - "where42": URL(string:"https://www.where42.kr")!, - "cabi": URL(string:"https://cabi.42seoul.io/")!, - "42gg": URL(string:"https://42gg.kr/")!, - ] + var id: UUID + var name: String + var url: String + init(name: String, url: String) { + self.id = UUID() + self.name = name + self.url = url + } +} + +struct URLModels { + var info: [URLModel] + + // Network logic let URLstring: [(String, String)] = [ ("home", "https://42box.github.io/front-end/"), // ("home", "http://127.0.0.1:3000/"), @@ -34,5 +35,12 @@ struct URLModel { ("where42", "https://www.where42.kr"), ("cabi", "https://cabi.42seoul.io/"), ("42gg", "https://42gg.kr/"), + ("textart", "https://textart.sh/") ] + + mutating func urlSetup() { + URLstring.forEach { (name, url) in + info.append(URLModel(name: name, url: url)) + } + } } From ec0aa903156a4ad73d2c920dd766ca861c2442ba Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 11 Aug 2023 04:06:58 +0900 Subject: [PATCH 09/55] =?UTF-8?q?feat:=20=EC=A0=84=EC=97=AD=EA=B4=80?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/CPU/CPU.swift | 10 ++-------- Box42/Preferences/Icon.swift | 13 ++++++++++++- Box42/Resources/AppDelegate.swift | 2 +- Box42/Resources/Box42.entitlements | 2 ++ Box42/Resources/Info.plist | 21 +++++++++++++++++++++ Box42/Shared/StateManager.swift | 30 +++++++++++++++++++++++++++++- 6 files changed, 67 insertions(+), 11 deletions(-) diff --git a/Box42/CPU/CPU.swift b/Box42/CPU/CPU.swift index 7f59495..1d31df6 100644 --- a/Box42/CPU/CPU.swift +++ b/Box42/CPU/CPU.swift @@ -10,7 +10,6 @@ import Foundation public class CPU { var cpuTimer: Timer? = nil - var isShow: Bool = false var usage: (value: Double, description: String) = (0.0, "") private let loadInfoCount: mach_msg_type_number_t! @@ -49,22 +48,17 @@ public class CPU { self.usage = (value, description) } - public func isShowUsage() -> Bool { - if isShow == false { return false } - return true - } - func processCPU(_ statusBar: StatusBar) -> Bool { 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 = self.isShowUsage() ? self.usage.description : "" + statusBar.statusItem.button?.title = StateManager.shared.getIsShowCPUUsage() ? self.usage.description : "" }) self.cpuTimer?.fire() return true } - public func StopCPU() -> Bool { + func StopCPU() -> Bool { self.cpuTimer?.invalidate() return false } diff --git a/Box42/Preferences/Icon.swift b/Box42/Preferences/Icon.swift index faca984..d256436 100644 --- a/Box42/Preferences/Icon.swift +++ b/Box42/Preferences/Icon.swift @@ -5,4 +5,15 @@ // Created by Chanhee Kim on 7/8/23. // -import Foundation +struct iconModel { + var icon: [String] = [ + "Cat", + "gam", + "gon", + "gun", + "lee", + "Box", + "box_oc", + "42" + ] +} diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 5eaba15..358a56c 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -10,7 +10,7 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { var menubarController = MenubarViewController() - + func applicationWillFinishLaunching(_ notification: Notification) { menubarController.menubarViewControllerInit() } diff --git a/Box42/Resources/Box42.entitlements b/Box42/Resources/Box42.entitlements index 40b639e..aa078cb 100644 --- a/Box42/Resources/Box42.entitlements +++ b/Box42/Resources/Box42.entitlements @@ -4,6 +4,8 @@ com.apple.security.app-sandbox + com.apple.security.automation.apple-events + com.apple.security.files.user-selected.read-only com.apple.security.network.client diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist index a6a98a7..6529386 100644 --- a/Box42/Resources/Info.plist +++ b/Box42/Resources/Info.plist @@ -28,5 +28,26 @@ Main NSPrincipalClass NSApplication + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + + UISceneDelegateClassName + + UISceneConfigurationName + + UISceneStoryboardFile + + + + + diff --git a/Box42/Shared/StateManager.swift b/Box42/Shared/StateManager.swift index e544e11..c5a0fec 100644 --- a/Box42/Shared/StateManager.swift +++ b/Box42/Shared/StateManager.swift @@ -8,9 +8,37 @@ class StateManager { static let shared = StateManager() - var isPin: Bool! + private var isPin: Bool! + private var isShowCPUUsage: Bool! + private var isShowWindow: Bool! private init() { isPin = false + isShowCPUUsage = false + isShowWindow = false + } + + func getIsPin() -> Bool { + return isPin + } + + func setToggleIsPin() { + isPin.toggle() + } + + func getIsShowCPUUsage() -> Bool { + return isShowCPUUsage + } + + func setToggleIsShowCPUUsage() { + isShowCPUUsage.toggle() + } + + func getToggleIsShowWindow() -> Bool { + return isShowWindow + } + + func setToggleIsShowWindow() { + isShowWindow.toggle() } } From 1be7520b127e9200188513a4163f53f7d371ad54 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 11 Aug 2023 04:07:45 +0900 Subject: [PATCH 10/55] =?UTF-8?q?refactor:=20mvc=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EB=A5=BC=20mvvm=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=B4=EA=B0=80=EB=8A=94=20=EA=B3=BC=EC=A0=95?= =?UTF-8?q?=EC=97=90=20=EC=9E=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/BoxButtonHandler.swift | 16 ++ Box42/Box/BoxModel.swift | 18 +- Box42/Box/BoxView.swift | 27 --- Box42/Box/BoxViewController.swift | 262 +++++++------------------ Box42/Box/BoxViewModel.swift | 29 +++ Box42/Box/View/BoxButtonView.swift | 123 ++++++++++++ Box42/Box/View/BoxView.swift | 101 ++++++++++ Box42/WebView/WebViewController.swift | 9 +- Box42/Window/BoxWindowController.swift | 26 +++ 9 files changed, 387 insertions(+), 224 deletions(-) create mode 100644 Box42/Box/BoxButtonHandler.swift delete mode 100644 Box42/Box/BoxView.swift create mode 100644 Box42/Box/BoxViewModel.swift create mode 100644 Box42/Box/View/BoxButtonView.swift create mode 100644 Box42/Box/View/BoxView.swift create mode 100644 Box42/Window/BoxWindowController.swift diff --git a/Box42/Box/BoxButtonHandler.swift b/Box42/Box/BoxButtonHandler.swift new file mode 100644 index 0000000..f79d076 --- /dev/null +++ b/Box42/Box/BoxButtonHandler.swift @@ -0,0 +1,16 @@ +// +// BoxButtonHandler.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxButtonHandler { + var clickAction: ((NSButton) -> Void)? + + @objc func buttonClicked(_ sender: NSButton) { + clickAction?(sender) + } +} diff --git a/Box42/Box/BoxModel.swift b/Box42/Box/BoxModel.swift index d6f114c..686ced2 100644 --- a/Box42/Box/BoxModel.swift +++ b/Box42/Box/BoxModel.swift @@ -2,11 +2,21 @@ // BoxViewModel.swift // Box42 // -// Created by Chan on 2023/03/16. +// Created by Chan on 2023/08/11. // -import WebKit +import Cocoa -public class BoxStatus { - var isPin: Bool = false +struct BoxViewSize { + var halfSize: (width: CGFloat, height: CGFloat)! + var size: (width: CGFloat, height: CGFloat)! + var buttonGroupSize: (width: CGFloat, height: CGFloat)! + var viewStack: [NSView?] + + init() { + halfSize = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) + size = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) + buttonGroupSize = (CGFloat(132), NSScreen.customScreenSize.y) + viewStack = [NSView()] + } } diff --git a/Box42/Box/BoxView.swift b/Box42/Box/BoxView.swift deleted file mode 100644 index 9e5ba10..0000000 --- a/Box42/Box/BoxView.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// BoxView.swift -// Box42 -// -// Created by Chan on 2023/03/17. -// - -import Cocoa - -class BoxView: NSView { - -} - -struct BoxViewSize { - var halfSize: (width: CGFloat, height: CGFloat) = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) - var size: (width: CGFloat, height: CGFloat) = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) - var buttonGroupSize: (width: CGFloat, height: CGFloat) = (CGFloat(132), NSScreen.customScreenSize.y) - var viewStack = [NSView()] -} - -extension NSScreen { - static let screenSize = NSScreen.main?.visibleFrame.size - static let screenWidth = screenSize!.width - static let screenHeight = screenSize!.height - static let halfOfScreen = (x: screenWidth / 2, y: screenHeight / 2) - static let customScreenSize = (x: CGFloat(900), y: screenHeight - 132) -} diff --git a/Box42/Box/BoxViewController.swift b/Box42/Box/BoxViewController.swift index 9d19ef9..784840c 100644 --- a/Box42/Box/BoxViewController.swift +++ b/Box42/Box/BoxViewController.swift @@ -10,175 +10,28 @@ import AppKit import WebKit class BoxViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - var ad = NSApplication.shared.delegate as? AppDelegate - let url = URLModel() + var boxView: BoxButtonView! + var boxVM: BoxViewModel! var wvc = WebViewController() let preferencesVC = PreferencesViewController() - var topAnchorDistance: CGFloat = 0 - - @IBOutlet var divider: NSBox! - @IBOutlet weak var boxView: NSView! - @IBOutlet weak var buttonViewGroup: NSView! - @IBOutlet weak var hostingViewGroup: NSView! - @IBOutlet var pinSwitch: NSSwitch! - private var webView: WKWebView! - private var buttonBoxGroup: NSView! - override func keyDown(with event: NSEvent) { - print(event.keyCode) - if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. - print("escape") - } else { - super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 - } - - if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { - // 복사 동작 처리 - webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in - if let error = error { - print("Copy error: \(error)") - } else { - print("Copy success") - } - } - } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { - // 붙여넣기 동작 처리 - let pasteboard = NSPasteboard.general - if let pasteString = pasteboard.string(forType: .string) { - let escapedPasteString = pasteString.escapedForJavaScript - webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in - if let error = error { - print("Paste error: \(error)") - } else { - print("Paste success") - } - } - } - } else { - super.keyDown(with: event) // 기본 키 이벤트 처리 - } + override func loadView() { + boxView = BoxButtonView() + boxVM = BoxViewModel() } override func viewDidLoad() { - view.window?.makeFirstResponder(self) super.viewDidLoad() - buttonBoxGroupInit() - boxViewSizeInit() + view.window?.styleMask.insert(.resizable) + view.window?.makeFirstResponder(self) + webViewInit() wvc.loadWebViewInit() configureButton() } - - func createButton(_ title :String) { - let button = NSButton() - - button.title = title - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(self.clickBtn(sender:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 30 - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createHomeButton() { - let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: (Any).self, action: #selector(self.clickBtn(sender:))) - button.translatesAutoresizingMaskIntoConstraints = false - button.isBordered = false - button.imagePosition = .imageOnly - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 80 - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createQuitButton() { - let button = NSButton() - button.title = "Quit Box" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(NSApplication.terminate(_:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -10).isActive = true - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func divide() { - divider.translatesAutoresizingMaskIntoConstraints = false - divider.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -40).isActive = true - } - - func createPinButton() { - let button = NSButton() - button.title = "Pin Box" - button.setButtonType(.toggle) - button.contentTintColor = .orange - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(self.pin) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -50).isActive = true - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func preferencesButton() { - let button = NSButton() - button.title = "Preferences" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(self.clickBtn(sender:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -90).isActive = true - button.trailingAnchor.constraint(equalTo: buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func configureButton() { - createHomeButton() - for i in 1.. 2 { - let rqURL = URLRequest(url: URLModel().URLdict[sender.title]!) + let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) WebViewList.shared.list[sender.title]!.load(rqURL) print("Triple Click") } else if clickCount < 2 { - hostingViewGroup.subviews.removeAll() - hostingViewGroup.addSubview(WebViewList.shared.list[sender.title]!) + boxView.hostingViewGroup.subviews.removeAll() + boxView.hostingViewGroup.addSubview(WebViewList.shared.list[sender.title]!) WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() - setAutoLayout(from: WebViewList.shared.list[sender.title]!, to: hostingViewGroup) + setAutoLayout(from: WebViewList.shared.list[sender.title]!, to: boxView.hostingViewGroup) } } @objc func pin(_ sender: NSSwitch) { - StateManager.shared.isPin.toggle() + StateManager.shared.setToggleIsPin() print(sender.state) } - func boxViewSizeInit() { - boxView.frame.size.width = BoxViewSize().size.width - boxView.frame.size.height = BoxViewSize().size.height - - hostingViewGroup.frame.size.width = BoxViewSize().size.width - BoxViewSize().buttonGroupSize.width - hostingViewGroup.frame.size.height = BoxViewSize().size.height - - buttonViewGroup.frame.size.width = BoxViewSize().buttonGroupSize.width - buttonViewGroup.frame.size.height = BoxViewSize().buttonGroupSize.height - } - - func buttonBoxGroupInit() { - buttonBoxGroup = NSView(frame: NSRect(x: 0, y: 0, width: BoxViewSize().buttonGroupSize.width, height: BoxViewSize().buttonGroupSize.height)) - buttonBoxGroup.frame.size.width = BoxViewSize().buttonGroupSize.width - buttonBoxGroup.frame.size.height = BoxViewSize().buttonGroupSize.height - buttonViewGroup.addSubview(buttonBoxGroup) - - setAutoLayout(from: buttonBoxGroup, to: buttonViewGroup) - } - func webViewInit() { + boxVM.setUpURLdict() webView = wvc.addWebView() - hostingViewGroup.addSubview(webView) - setAutoLayout(from: webView, to: hostingViewGroup) - let request = URLRequest(url: url.URLdict["home"]!) + boxView.hostingViewGroup.addSubview(webView) + setAutoLayout(from: webView, to: boxView.hostingViewGroup) + let request = URLRequest(url: boxVM.URLdict["home"]!) DispatchQueue.main.async { self.webView.load(request) } @@ -260,16 +94,66 @@ class BoxViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { print(message.name) } + + func configureButton() { + boxView.createHomeButton(clickAction: clickBtn) + for (name, _) in boxVM.webViewURL.URLstring { + boxView.createButton(name, clickAction: clickBtn) + } + boxView.divide() + boxView.preferencesButton(clickAction: clickBtn) + boxView.createQuitButton() + boxView.createPinButton(clickAction: clickBtn) + } } extension BoxViewController { static func freshController() -> BoxViewController { let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) - let identifier = NSStoryboard.SceneIdentifier("BoxController") - + let identifier = NSStoryboard.SceneIdentifier("Main") + guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxViewController else { fatalError("Story Board Not Found") } return viewcontroller } } + +extension BoxViewController { + override func keyDown(with event: NSEvent) { + print(event.keyCode) + if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. + print("escape") + } else { + super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 + } + + if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { + // 복사 동작 처리 + webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in + if let error = error { + print("Copy error: \(error)") + } else { + print("Copy success") + } + } + } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { + // 붙여넣기 동작 처리 + let pasteboard = NSPasteboard.general + if let pasteString = pasteboard.string(forType: .string) { + let escapedPasteString = pasteString.escapedForJavaScript + webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in + if let error = error { + print("Paste error: \(error)") + } else { + print("Paste success") + } + } + } + } else { + super.keyDown(with: event) // 기본 키 이벤트 처리 + } + } +} diff --git a/Box42/Box/BoxViewModel.swift b/Box42/Box/BoxViewModel.swift new file mode 100644 index 0000000..3fbd9ff --- /dev/null +++ b/Box42/Box/BoxViewModel.swift @@ -0,0 +1,29 @@ +// +// URLViewModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/9/23. +// + +import Foundation +import Combine + +// CRUD 4가지 형태의 데이터 가공 create, read, update, delete +class BoxViewModel: ObservableObject { + var webViewURL: URLModels + @Published var URLdict: [String: URL] + + init() { + self.webViewURL = URLModels(info: [URLModel(name: "home", url: "https://42box.github.io/front-end/")]) + self.URLdict = [String: URL]() + } + + func setUpURLdict() { +// for urlModel in webViewURL.info { +// URLdict[urlModel.name] = URL(string: urlModel.url) +// } + for urlModel in webViewURL.URLstring { + URLdict[urlModel.0] = URL(string: urlModel.1) + } + } +} diff --git a/Box42/Box/View/BoxButtonView.swift b/Box42/Box/View/BoxButtonView.swift new file mode 100644 index 0000000..37a9a6f --- /dev/null +++ b/Box42/Box/View/BoxButtonView.swift @@ -0,0 +1,123 @@ +// +// BoxButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxButtonView: BoxView { + var topAnchorDistance: CGFloat = 0 + + func createButton(_ title: String, clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + + button.title = title + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 30 + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createHomeButton(clickAction: @escaping (NSButton) -> Void) { + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: handler, action: #selector(handler.buttonClicked(_:))) + + button.translatesAutoresizingMaskIntoConstraints = false + button.isBordered = false + button.imagePosition = .imageOnly + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 80 + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createQuitButton() { + let button = NSButton() + button.title = "Quit Box" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(NSApplication.terminate(_:)) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -10).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createPinButton(clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + button.title = "Pin Box" + button.setButtonType(.toggle) + button.contentTintColor = .orange + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -50).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func preferencesButton(clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + button.title = "Preferences" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -90).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + +} diff --git a/Box42/Box/View/BoxView.swift b/Box42/Box/View/BoxView.swift new file mode 100644 index 0000000..c20ca54 --- /dev/null +++ b/Box42/Box/View/BoxView.swift @@ -0,0 +1,101 @@ +// +// BoxView.swift +// Box42 +// +// Created by Chan on 2023/03/17. +// + +import Cocoa + +class BoxView: NSView { + var buttonBoxGroup : NSView! + var buttonViewGroup : NSView! + var hostingViewGroup : NSView! + var divider : NSBox! + var pinSwitch : NSSwitch! + var boxModel = BoxViewSize() + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + commonInit() + viewInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + viewInit() + } + + private func commonInit() { + buttonBoxGroup = NSView() + buttonViewGroup = NSView() + hostingViewGroup = NSView() + divider = NSBox() + pinSwitch = NSSwitch() + + // Pan Gesture Recognizer를 추가합니다. + let panRecognizer = NSPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) + addGestureRecognizer(panRecognizer) + } + + func viewInit() { + self.boxViewSizeInit() + self.buttonBoxGroupInit() + self.divide() + } + + func boxViewSizeInit() { + self.frame.size.width = boxModel.size.width + self.frame.size.height = boxModel.size.height + + hostingViewGroup.frame.size.width = boxModel.size.width - boxModel.buttonGroupSize.width + hostingViewGroup.frame.size.height = boxModel.size.height + + buttonViewGroup.frame.size.width = boxModel.buttonGroupSize.width + buttonViewGroup.frame.size.height = boxModel.buttonGroupSize.height + } + + func divide() { + divider.translatesAutoresizingMaskIntoConstraints = false + divider.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -40).isActive = true + } + + func buttonBoxGroupInit() { + self.buttonBoxGroup = NSView(frame: NSRect(x: 0, y: 0, width: boxModel.buttonGroupSize.width, height: boxModel.buttonGroupSize.height)) + self.buttonBoxGroup.frame.size.width = boxModel.buttonGroupSize.width + self.buttonBoxGroup.frame.size.height = boxModel.buttonGroupSize.height + self.buttonViewGroup.addSubview(self.buttonBoxGroup) + + setAutoLayout(from: self.buttonBoxGroup, to: self.buttonViewGroup) + } + + func setAutoLayout(from: NSView, to: NSView) { + from.translatesAutoresizingMaskIntoConstraints = false + to.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true + NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true + self.layout() + } +} + +extension BoxView { + @objc private func handlePanGesture(_ recognizer: NSPanGestureRecognizer) { + guard let view = recognizer.view else { return } + + // 사용자가 드래그한 변화량을 가져옵니다. + let translation = recognizer.translation(in: view) + + // 드래그로 인한 크기 변화를 계산합니다. + let newWidth = view.frame.width + translation.x + let newHeight = view.frame.height + translation.y + + // 크기를 적용합니다. + view.setFrameSize(NSSize(width: newWidth, height: newHeight)) + + // 변화량을 리셋합니다. + recognizer.setTranslation(.zero, in: view) + } +} diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 13909a4..984f888 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -9,12 +9,13 @@ import Cocoa import WebKit class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - + var URLVM = BoxViewModel() + func loadWebViewInit() { - for i in 0.. Date: Fri, 11 Aug 2023 04:09:21 +0900 Subject: [PATCH 11/55] =?UTF-8?q?feat:=20xib=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Window/BoxWindowController.xib | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Box42/Window/BoxWindowController.xib diff --git a/Box42/Window/BoxWindowController.xib b/Box42/Window/BoxWindowController.xib new file mode 100644 index 0000000..30df79a --- /dev/null +++ b/Box42/Window/BoxWindowController.xib @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From dfd3049c0ebce2221c0a6f2e3170e15e225821b7 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Mon, 14 Aug 2023 05:32:59 +0900 Subject: [PATCH 12/55] =?UTF-8?q?feat(Script=F0=9F=93=83):=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=86=A0=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=ED=95=A9=EB=8B=88=EB=8B=A4=20(#22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(Script📃): prototype을 완성하였습니다. * test(🖥): 테스트를 위해 xcodeproj를 등록합니다. * docs: .gitignore * test(🖥): 테스트를 위해 xcodeproj를 등록합니다. * feat: add script files --- .gitignore | 3 + Box42.xcodeproj/project.pbxproj | 561 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 187119 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 + .../xcschemes/xcschememanagement.plist | 14 + Box42/Preferences/PreferencesController.swift | 104 +++- Box42/Resources/Main.storyboard | 68 +-- Box42/Scripts/Scripts.swift | 25 + Box42/Scripts/sh/brewInGoinfre.sh | 63 ++ Box42/Scripts/sh/cleanCache.sh | 157 +++++ Box42/Scripts/sh/exportMacOSInfo.sh | 1 + Box42/Scripts/sh/importMacOSInfo.sh | 1 + Box42/Scripts/sh/keyMapping.sh | 146 +++++ Box42/Scripts/sh/nodeInstall.sh | 69 +++ 16 files changed, 1164 insertions(+), 69 deletions(-) create mode 100644 Box42.xcodeproj/project.pbxproj create mode 100644 Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 Box42/Scripts/Scripts.swift create mode 100644 Box42/Scripts/sh/brewInGoinfre.sh create mode 100755 Box42/Scripts/sh/cleanCache.sh create mode 100644 Box42/Scripts/sh/exportMacOSInfo.sh create mode 100644 Box42/Scripts/sh/importMacOSInfo.sh create mode 100644 Box42/Scripts/sh/keyMapping.sh create mode 100644 Box42/Scripts/sh/nodeInstall.sh diff --git a/.gitignore b/.gitignore index dd2592e..f24b421 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .DS_Store Box42/.DS_Store + +.prettierrc +.swift-format \ No newline at end of file diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj new file mode 100644 index 0000000..90cda27 --- /dev/null +++ b/Box42.xcodeproj/project.pbxproj @@ -0,0 +1,561 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */; }; + DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */; }; + DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */; }; + DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */; }; + DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE32A509B1700FF0AA3 /* CPU.swift */; }; + DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */; }; + DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */; }; + DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEC2A509B2600FF0AA3 /* URLModel.swift */; }; + DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */; }; + DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; + DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; + DE018BF92A509B3B00FF0AA3 /* BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */; }; + DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */; }; + DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFE2A509B4200FF0AA3 /* BoxView.swift */; }; + DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; + DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; + DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; + DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; + DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesController.swift */; }; + 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 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; + DE9BCA0D2A8360460031CA7B /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9BCA0C2A8360460031CA7B /* BoxViewModel.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 */; }; + DEB862EC2A853F7F00278FCD /* BoxWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */; }; + DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; + DEF749372A8565C400D987C8 /* BoxButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749362A8565C400D987C8 /* BoxButtonView.swift */; }; + DEF7493B2A85683F00D987C8 /* BoxButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + DE018BAF2A5099F900FF0AA3 /* Box42.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Box42.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Box42.xcdatamodel; sourceTree = ""; }; + DE018BBE2A5099FA00FF0AA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; + DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DE018BE32A509B1700FF0AA3 /* CPU.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = ""; }; + DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; + DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = ""; }; + DE018BEC2A509B2600FF0AA3 /* URLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLModel.swift; sourceTree = ""; }; + DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarViewController.swift; sourceTree = ""; }; + DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; + DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; + DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxViewController.swift; sourceTree = ""; }; + DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxModel.swift; sourceTree = ""; }; + DE018BFE2A509B4200FF0AA3 /* BoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; + DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; + DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.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 /* PreferencesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesController.swift; 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 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + DE9BCA0C2A8360460031CA7B /* BoxViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxViewModel.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 = ""; }; + DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BoxWindowController.xib; 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 = ""; }; + DEF749362A8565C400D987C8 /* BoxButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxButtonView.swift; sourceTree = ""; }; + DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxButtonHandler.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DE018BAC2A5099F900FF0AA3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DE018BA62A5099F900FF0AA3 = { + isa = PBXGroup; + children = ( + DE018BB12A5099F900FF0AA3 /* Box42 */, + DE018BB02A5099F900FF0AA3 /* Products */, + DE17AF722A834A1600325BF4 /* Frameworks */, + ); + sourceTree = ""; + }; + DE018BB02A5099F900FF0AA3 /* Products */ = { + isa = PBXGroup; + children = ( + DE018BAF2A5099F900FF0AA3 /* Box42.app */, + ); + name = Products; + sourceTree = ""; + }; + DE018BB12A5099F900FF0AA3 /* Box42 */ = { + isa = PBXGroup; + children = ( + DEF749302A85655E00D987C8 /* Extensions */, + DEB862E82A853F6800278FCD /* Window */, + DEB862D22A8511D600278FCD /* Scripts */, + DE77BA542A82636500713683 /* Shared */, + DE874F512A591EC600FC3B77 /* Preferences */, + DE018C0C2A509BDF00FF0AA3 /* Resources */, + DE018C062A509B9000FF0AA3 /* CPU */, + DE018C082A509BB500FF0AA3 /* WebView */, + DE018C0B2A509BC100FF0AA3 /* URL */, + DE018C0E2A509C0C00FF0AA3 /* Menubar */, + DE018C102A509C1A00FF0AA3 /* Box */, + ); + path = Box42; + sourceTree = ""; + }; + DE018C062A509B9000FF0AA3 /* CPU */ = { + isa = PBXGroup; + children = ( + DE018BE32A509B1700FF0AA3 /* CPU.swift */, + ); + path = CPU; + sourceTree = ""; + }; + DE018C082A509BB500FF0AA3 /* WebView */ = { + isa = PBXGroup; + children = ( + DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, + DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, + ); + path = WebView; + sourceTree = ""; + }; + DE018C0B2A509BC100FF0AA3 /* URL */ = { + isa = PBXGroup; + children = ( + DE018BEC2A509B2600FF0AA3 /* URLModel.swift */, + ); + path = URL; + sourceTree = ""; + }; + DE018C0C2A509BDF00FF0AA3 /* Resources */ = { + isa = PBXGroup; + children = ( + DE018C192A509DBA00FF0AA3 /* Box42.entitlements */, + DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */, + DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, + DE018BBE2A5099FA00FF0AA3 /* Info.plist */, + DE018C022A509B5D00FF0AA3 /* Main.storyboard */, + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, + DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */, + ); + path = Resources; + sourceTree = ""; + }; + DE018C0E2A509C0C00FF0AA3 /* Menubar */ = { + isa = PBXGroup; + children = ( + DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */, + DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */, + DE018BF52A509B3600FF0AA3 /* MenubarView.swift */, + DE77BA502A82580400713683 /* MenubarViewModel.swift */, + ); + path = Menubar; + sourceTree = ""; + }; + DE018C102A509C1A00FF0AA3 /* Box */ = { + isa = PBXGroup; + children = ( + DEF749352A8565B000D987C8 /* View */, + DE9BCA0C2A8360460031CA7B /* BoxViewModel.swift */, + DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */, + DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */, + DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */, + ); + path = Box; + sourceTree = ""; + }; + DE17AF722A834A1600325BF4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + DE77BA542A82636500713683 /* Shared */ = { + isa = PBXGroup; + children = ( + DE77BA552A82637900713683 /* StateManager.swift */, + ); + path = Shared; + sourceTree = ""; + }; + DE874F512A591EC600FC3B77 /* Preferences */ = { + isa = PBXGroup; + children = ( + DE7A25792A6D8CA20043225A /* PreferencesController.swift */, + DE874F532A591F1400FC3B77 /* PreferencesView.swift */, + DE874F562A591F2500FC3B77 /* Icon.swift */, + DE2AD3282A824EEB00002D51 /* Accessibility.swift */, + DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */, + ); + path = Preferences; + sourceTree = ""; + }; + DEB862D22A8511D600278FCD /* Scripts */ = { + isa = PBXGroup; + children = ( + DEB862DE2A85348600278FCD /* sh */, + DEB862DB2A85347400278FCD /* Scripts.swift */, + ); + path = Scripts; + sourceTree = ""; + }; + DEB862DE2A85348600278FCD /* sh */ = { + isa = PBXGroup; + children = ( + DEB862D32A85124500278FCD /* cleanCache.sh */, + DEB862D82A852C4500278FCD /* brewInGoinfre.sh */, + DEF7492E2A85603700D987C8 /* nodeInstall.sh */, + ); + path = sh; + sourceTree = ""; + }; + DEB862E82A853F6800278FCD /* Window */ = { + isa = PBXGroup; + children = ( + DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, + DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */, + ); + path = Window; + sourceTree = ""; + }; + DEF749302A85655E00D987C8 /* Extensions */ = { + isa = PBXGroup; + children = ( + DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */, + DEF749312A85657600D987C8 /* NSScreen.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + DEF749352A8565B000D987C8 /* View */ = { + isa = PBXGroup; + children = ( + DE018BFE2A509B4200FF0AA3 /* BoxView.swift */, + DEF749362A8565C400D987C8 /* BoxButtonView.swift */, + ); + path = View; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DE018BAE2A5099F900FF0AA3 /* Box42 */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */; + buildPhases = ( + DE018BAB2A5099F900FF0AA3 /* Sources */, + DE018BAC2A5099F900FF0AA3 /* Frameworks */, + DE018BAD2A5099F900FF0AA3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Box42; + productName = Box42; + productReference = DE018BAF2A5099F900FF0AA3 /* Box42.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DE018BA72A5099F900FF0AA3 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1230; + LastUpgradeCheck = 1230; + TargetAttributes = { + DE018BAE2A5099F900FF0AA3 = { + CreatedOnToolsVersion = 12.3; + }; + }; + }; + buildConfigurationList = DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = DE018BA62A5099F900FF0AA3; + productRefGroup = DE018BB02A5099F900FF0AA3 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DE018BAE2A5099F900FF0AA3 /* Box42 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DE018BAD2A5099F900FF0AA3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */, + DEB862D42A85124500278FCD /* cleanCache.sh in Resources */, + DEB862EC2A853F7F00278FCD /* BoxWindowController.xib in Resources */, + DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */, + DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DE018BAB2A5099F900FF0AA3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */, + DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, + DE9BCA0D2A8360460031CA7B /* BoxViewModel.swift in Sources */, + DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, + DE77BA562A82637900713683 /* StateManager.swift in Sources */, + DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, + DEF749372A8565C400D987C8 /* BoxButtonView.swift in Sources */, + DEF7493B2A85683F00D987C8 /* BoxButtonHandler.swift in Sources */, + DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, + DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, + DE018BF92A509B3B00FF0AA3 /* BoxViewController.swift in Sources */, + DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, + DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, + DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, + DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, + DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, + DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, + DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, + DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */, + DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, + DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, + DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */, + DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, + DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, + DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, + DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, + DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + DE018BC02A5099FA00FF0AA3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DE018BC12A5099FA00FF0AA3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + DE018BC32A5099FA00FF0AA3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Box42/Resources/Box42.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Box42/Resources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + DE018BC42A5099FA00FF0AA3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Box42/Resources/Box42.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Box42/Resources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.chanheki.Box42; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DE018BAA2A5099F900FF0AA3 /* Build configuration list for PBXProject "Box42" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE018BC02A5099FA00FF0AA3 /* Debug */, + DE018BC12A5099FA00FF0AA3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE018BC22A5099FA00FF0AA3 /* Build configuration list for PBXNativeTarget "Box42" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE018BC32A5099FA00FF0AA3 /* Debug */, + DE018BC42A5099FA00FF0AA3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */, + ); + currentVersion = DE018BB72A5099F900FF0AA3 /* Box42.xcdatamodel */; + path = Box42.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = DE018BA72A5099F900FF0AA3 /* Project object */; +} diff --git a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..6643712816c4033543191d1bfd4fcf964579c85c GIT binary patch literal 187119 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²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

xRh1ZpM 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 bXCC*2{`XHL{KcOKw14sE|NkBC{^NfEMg5Gb literal 0 HcmV?d00001 diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..955e565 --- /dev/null +++ b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..2d4f387 --- /dev/null +++ b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Box42.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Box42/Preferences/PreferencesController.swift b/Box42/Preferences/PreferencesController.swift index 60f6151..1b9139b 100644 --- a/Box42/Preferences/PreferencesController.swift +++ b/Box42/Preferences/PreferencesController.swift @@ -6,16 +6,18 @@ // import Cocoa +import Foundation class PreferencesViewController: NSViewController { - + let menubarVC = MenubarViewController() private var stackView: NSStackView! private var rightView: NSView! + private var outputView: NSTextView! override func loadView() { self.view = NSView() self.stackView = NSStackView() - self.stackView.orientation = .horizontal + self.stackView.orientation = .vertical self.stackView.distribution = .fillEqually self.stackView.spacing = 20 self.view.addSubview(stackView) @@ -32,10 +34,39 @@ class PreferencesViewController: NSViewController { self.stackView.addArrangedSubview(leftView) self.stackView.addArrangedSubview(rightView) - let iconButton = NSButton(title: "Change Icon", target: self, action: #selector(changeIconButtonPressed)) - let cronButton = NSButton(title: "Cron Script", target: self, action: #selector(cronButtonPressed)) + outputView = NSTextView() + outputView.translatesAutoresizingMaskIntoConstraints = false + rightView.addSubview(outputView) + + NSLayoutConstraint.activate([ + outputView.topAnchor.constraint(equalTo: rightView.topAnchor), + outputView.leadingAnchor.constraint(equalTo: rightView.leadingAnchor), + outputView.trailingAnchor.constraint(equalTo: rightView.trailingAnchor), + outputView.bottomAnchor.constraint(equalTo: rightView.bottomAnchor) + ]) + + + var stackBox: [NSView] = [] + + let icons = iconModel().icon + icons.forEach { (icon) in + stackBox.append(NSButton(title: "Change \(icon) Icon", target: self, action: #selector(changeIconButtonPressed))) + } + + let scripts = Scripts().info + scripts.forEach { (script) in + stackBox.append(NSButton(title: "\(script.name) Script: \(script.description)", target: self, action: #selector(scriptButtonPressed))) + + } + +// let scriptButton = NSButton(title: "Script", target: self, action: #selector(scriptButtonPressed)) + let appleScriptButton = NSButton(title: "Apple Script", target: self, action: #selector(scriptButtonPressed)) let etcButton = NSButton(title: "Etc.", target: self, action: #selector(etcButtonPressed)) - let buttonStackView = NSStackView(views: [iconButton, cronButton, etcButton]) + +// stackBox.append(scriptButton) + stackBox.append(appleScriptButton) + stackBox.append(etcButton) + let buttonStackView = NSStackView(views: stackBox) buttonStackView.orientation = .vertical buttonStackView.distribution = .fillEqually buttonStackView.spacing = 20 @@ -49,12 +80,69 @@ class PreferencesViewController: NSViewController { ]) } - @objc func changeIconButtonPressed() { + @objc func changeIconButtonPressed(_ sender: NSButton) { // Change the content of the right view for icon changing + let icon = sender.title.split(separator: " ").map{String($0)} + print(icon[1]) + menubarVC.menubarStopRunning() + menubarVC.buttonImageChange(icon[1]) + menubarVC.menubarStartRunning() } - @objc func cronButtonPressed() { - // Change the content of the right view for cron script selection + @objc func scriptButtonPressed(_ sender: NSButton) { + let script = sender.title.split(separator: " ").map{String($0)} + if script[1] == "Script:" { + if let scriptPath = Bundle.main.path(forResource: script[0], ofType: "sh") { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = [scriptPath] + + let outputPipe = Pipe() + task.standardOutput = outputPipe + task.standardError = outputPipe + + + task.standardError = outputPipe + + outputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in + if #available(OSX 10.15.4, *) { + if let data = try? fileHandle.readToEnd(), let output = String(data: data, encoding: .utf8) { + DispatchQueue.main.async { + if let outputView = self?.outputView { + outputView.string += "\(output)" + } else { + print("outputView is nil") + } + } + } + } else { + // Fallback on earlier versions + } + } + + + task.launch() + task.waitUntilExit() + +// let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() +// let output = String(data: outputData, encoding: .utf8) ?? "" +// print("Output: \(output)") + } else { + print("Script not found") + } + } else if sender.title == "Apple Script" { + let appleScriptCode = "display dialog \"Hello, World!\"" + + if let appleScript = NSAppleScript(source: appleScriptCode) { + var errorDict: NSDictionary? = nil + appleScript.executeAndReturnError(&errorDict) + + if let error = errorDict { + print("Error: \(error)") + } + } + + } } @objc func etcButtonPressed() { diff --git a/Box42/Resources/Main.storyboard b/Box42/Resources/Main.storyboard index dbd2ec4..0a9696b 100644 --- a/Box42/Resources/Main.storyboard +++ b/Box42/Resources/Main.storyboard @@ -173,67 +173,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + + - + @@ -266,14 +216,10 @@ - - - - - + diff --git a/Box42/Scripts/Scripts.swift b/Box42/Scripts/Scripts.swift new file mode 100644 index 0000000..96323f7 --- /dev/null +++ b/Box42/Scripts/Scripts.swift @@ -0,0 +1,25 @@ +// +// Scripts.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Foundation + +struct Scripts { + var info: [(name: String, description: String)] = [("cleanCache", "cleaning cache"), ("brewInGoinfre", + "brew download in goinfre")] +} + +struct Script { + var id: UUID + var name: String + var description: String + + init(name: String, description: String) { + self.id = UUID() + self.name = name + self.description = description + } +} diff --git a/Box42/Scripts/sh/brewInGoinfre.sh b/Box42/Scripts/sh/brewInGoinfre.sh new file mode 100644 index 0000000..c97c200 --- /dev/null +++ b/Box42/Scripts/sh/brewInGoinfre.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +#42Box: https://github.com/42Box +#Author: chanheki +#Date: 2023/08/10 + +# BOXY FOX +echo "" +echo "\033[38;5;208m Boxy Fox, Brew download in goinfre" +echo "" +echo " ████████" +echo " ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒" +echo " ████ ██████" +echo " ██ ████" +echo " ██ ██" +echo " ██ ░░░░░░░░░░░░░░██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░██ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██ ██████ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░████ ██████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░████ ████████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░████ ████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒██▓▓▓▓" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██▒▒████░░░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░████░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░████░░░░░░░░░░██████████████░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░▒▒▒▒████░░░░░░██████▒▒▒▒████████░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░████░░░░████░░░░░░██████████░░░░░░████░░░░░░░░░░ ░░░░██" +echo " ░░▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓████▓▓░░░░▒▒████████▓▓▓▓▓▓▓▓▒▒░░░░░░░░░░ ░░░░██" +echo " ░░██░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒██████░░░░░░▒▒▒▒██████▒▒▒▒░░░░░░░░ ░░░░░░░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒████░░░░░░████▒▒ ░░░░░░ ░░░░ ░░░░██" +echo " ░░▓▓▓▓░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▓▓▒▒▒▒░░ ░░░░░░░░░░░░ ░░░░██" +echo " ░░░░▓▓▓▓░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓██▒▒░░░░░░░░░░░░░░ ░░░░ ░░██" +echo " ████░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░ ░░░░░░ ██ ░░██" +echo " ████░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ░░░░▓▓▓▓▓▓▓▓██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ░░░░ ███▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ▒▒██ ░░░░ ▒▒▒▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ░░░░ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ████ ██" +echo " ██████ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██" +echo " ████░░████ ░░░░░░░░░░░░░░░░░░░░░░██░░░░ ░░░░░░ ████" +echo " ████░░██░░██████ ░░░░░░░░░░░░░░░░░░██░░░░ ░░░░ ████" +echo " ██░░██░░░░██████████ ░░░░░░░░░░░░░░██░░░░ ██████████" +echo " ██████████████████████ ░░░░░░░░░░██░░░░ ████████████████" +echo " ██████████ ████ ░░░░░░██░░░░ ██████████████████████" +echo " ████ ░░██░░ ████ ████████████████" +echo " ████ ██ ██████████ ██████████" +echo " ████ ██ ████████████████ ██████" +echo " ████ ██ ██████████████████████" +echo " ██████ ████████████████" +echo " ██████████" +echo " ░░██████░░" +echo "" + +brew --version || echo "export PATH=/goinfre/.brew/bin:$PATH" >> ~/.zshrc && brew --version || git clone --depth=1 https://github.com/Homebrew/brew /goinfre/.brew && export PATH=/goinfre/.brew/bin:$PATH && brew update && ln -s /goinfre/.brew ~/.brew + +echo "Download Complete" diff --git a/Box42/Scripts/sh/cleanCache.sh b/Box42/Scripts/sh/cleanCache.sh new file mode 100755 index 0000000..4e0024f --- /dev/null +++ b/Box42/Scripts/sh/cleanCache.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +#42Box: https://github.com/42Box +#Author: chanheki +#Date: 2023/08/10 + +# BOXY FOX +echo "" +echo "\033[38;5;208m Boxy Fox Cleaning Cache" +echo "" +echo " ████████" +echo " ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒" +echo " ████ ██████" +echo " ██ ████" +echo " ██ ██" +echo " ██ ░░░░░░░░░░░░░░██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░██ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██ ██████ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░████ ██████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░████ ████████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░████ ████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒██▓▓▓▓" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██▒▒████░░░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░████░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░████░░░░░░░░░░██████████████░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░▒▒▒▒████░░░░░░██████▒▒▒▒████████░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░████░░░░████░░░░░░██████████░░░░░░████░░░░░░░░░░ ░░░░██" +echo " ░░▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓████▓▓░░░░▒▒████████▓▓▓▓▓▓▓▓▒▒░░░░░░░░░░ ░░░░██" +echo " ░░██░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒██████░░░░░░▒▒▒▒██████▒▒▒▒░░░░░░░░ ░░░░░░░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒████░░░░░░████▒▒ ░░░░░░ ░░░░ ░░░░██" +echo " ░░▓▓▓▓░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▓▓▒▒▒▒░░ ░░░░░░░░░░░░ ░░░░██" +echo " ░░░░▓▓▓▓░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓██▒▒░░░░░░░░░░░░░░ ░░░░ ░░██" +echo " ████░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░ ░░░░░░ ██ ░░██" +echo " ████░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ░░░░▓▓▓▓▓▓▓▓██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ░░░░ ███▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ▒▒██ ░░░░ ▒▒▒▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ░░░░ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ████ ██" +echo " ██████ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██" +echo " ████░░████ ░░░░░░░░░░░░░░░░░░░░░░██░░░░ ░░░░░░ ████" +echo " ████░░██░░██████ ░░░░░░░░░░░░░░░░░░██░░░░ ░░░░ ████" +echo " ██░░██░░░░██████████ ░░░░░░░░░░░░░░██░░░░ ██████████" +echo " ██████████████████████ ░░░░░░░░░░██░░░░ ████████████████" +echo " ██████████ ████ ░░░░░░██░░░░ ██████████████████████" +echo " ████ ░░██░░ ████ ████████████████" +echo " ████ ██ ██████████ ██████████" +echo " ████ ██ ████████████████ ██████" +echo " ████ ██ ██████████████████████" +echo " ██████ ████████████████" +echo " ██████████" +echo " ░░██████░░" +echo "" + +# Command +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[34m" +ORANGE="\033[38;5;208m" +# DELINE="\033[K" +# CURSUP="\033[A" +MAGENTA="\033[35m" +CYAN="\033[36m" +RESET="\033[0m" + +# Currently Size +Size=$(df -h ~ | grep ~ | awk '{print($2)}' | tr 'i' 'B') + +# Currently used capacity +Used=$(df -h ~ | grep ~ | awk '{print($3)}' | tr 'i' 'B') + +# Currently available capacity +Avail=$(df -h ~ | grep ~ | awk '{print($4)}' | tr 'i' 'B') +if [ "$Avail" == "0BB" ]; +then + Avail="0B" +fi + +echo "$CYAN Currently used capacity $Used/$Size $RESET\n" + +echo "$MAGENTA Clearing 🧹 cache ... $DELINE $RESET $CURSUP " + +# Trash +echo "$RED Clearing 🧹 trash can ...$DELINE $RESET $CURSUP " +rm -rf ~/.Trash/* &>/dev/null + +# 42 Caches +echo "$RED Clearing 🧹 42Cache ...$DELINE $RESET $CURSUP" +rm -rf ~/Library/*.42* &>/dev/null +rm -rf ~/*.42* &>/dev/null +rm -rf ~/.zcompdump* &>/dev/null +rm -rf ~/.cocoapods.42_cache_bak* &>/dev/null + +# General Caches +echo "$RED Clearing 🧹 Library ...$DELINE $RESET $CURSUP" +chmod -R 644 ~/Library/Caches/Homebrew &>/dev/null +rm -rf ~/Library/Caches/* &>/dev/null +rm -rf ~/Library/Application\ Support/Caches/* &>/dev/null + +echo "$RED Clearing 🧹 Slack ...$DELINE $RESET $CURSUP" +rm -rf ~/Library/Application\ Support/Slack/Service\ Worker/CacheAvail/* &>/dev/null +rm -rf ~/Library/Application\ Support/Slack/Cache/* &>/dev/null + +echo "$RED Clearing 🧹 Discord ...$DELINE $RESET $CURSUP" +rm -rf ~/Library/Application\ Support/discord/Cache/* &>/dev/null +rm -rf ~/Library/Application\ Support/discord/Code\ Cache/js* &>/dev/null +rm -rf ~/Library/Application\ Support/discord/Crashpad/completed/* &>/dev/null + +echo "$RED Clearing 🧹 VS Code ...$DELINE $RESET $CURSUP" +rm -rf ~/Library/Application\ Support/Code/Cache/* &>/dev/null +rm -rf ~/Library/Application\ Support/Code/CachedData/* &>/dev/null +rm -rf ~/Library/Application\ Support/Code/CachedExtensionVSIXs/* &>/dev/null +rm -rf ~/Library/Application\ Support/Code/Crashpad/completed/* &>/dev/null +rm -rf ~/Library/Application\ Support/Code/User/workspaceAvail/* &>/dev/null + +echo "$RED Clearing 🧹 Chrome ...$DELINE $RESET $CURSUP" +rm -rf ~/Library/Application\ Support/Google/Chrome/Profile\ [0-9]/Service\ Worker/CacheAvail/* &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Default/Service\ Worker/CacheAvail/* &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Profile\ [0-9]/Application\ Cache/* &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Default/Application\ Cache/* &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Crashpad/completed/* &>/dev/null +# tmp downloaded files with browsers +rm -rf ~/Library/Application\ Support/Chromium/Default/File\ System &>/dev/null +rm -rf ~/Library/Application\ Support/Chromium/Profile\ [0-9]/File\ System &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Default/File\ System &>/dev/null +rm -rf ~/Library/Application\ Support/Google/Chrome/Profile\ [0-9]/File\ System &>/dev/null + +# .DS_Store files +#echo "$RED Clearing 🧹 All .DS_Store ...$DELINE $RESET $CURSUP" +#find ~ -name .DS_Store -depth -exec rm {} \; &>/dev/null + +# Delete desktop +rm -rf ~/Desktop/Relocated Items &>/dev/null + +# Calculate usage after cleaning +Used=$(df -h ~ | grep ~ | awk '{print($3)}' | tr 'i' 'B') + +# Calculate usage after cleaning +Avail2=$(df -h ~ | grep ~ | awk '{print($4)}' | tr 'i' 'B') +if [ "$Avail2" == "0BB" ]; +then + Avail2="0B" +fi + +# Output the result +echo "\n$MAGENTA ✨ Complete Clearing cache ✨ $RESET \n" +echo "$GREEN Available/"$RED"Used/"$BLUE"Size "$GREEN"$Avail2/"$RED"$Used/"$BLUE"$Size $RESET\n" +echo "📦: https://github.com/42Box" +echo "🦊: chanheki in 42Box" +echo "" diff --git a/Box42/Scripts/sh/exportMacOSInfo.sh b/Box42/Scripts/sh/exportMacOSInfo.sh new file mode 100644 index 0000000..32eed6b --- /dev/null +++ b/Box42/Scripts/sh/exportMacOSInfo.sh @@ -0,0 +1 @@ +defaults export -g ~/.mysettings.plist diff --git a/Box42/Scripts/sh/importMacOSInfo.sh b/Box42/Scripts/sh/importMacOSInfo.sh new file mode 100644 index 0000000..070f87a --- /dev/null +++ b/Box42/Scripts/sh/importMacOSInfo.sh @@ -0,0 +1 @@ +defaults -currentHost import ~/.mysettings.plist diff --git a/Box42/Scripts/sh/keyMapping.sh b/Box42/Scripts/sh/keyMapping.sh new file mode 100644 index 0000000..3d8010f --- /dev/null +++ b/Box42/Scripts/sh/keyMapping.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +# keyMapping.sh +# Box42 +# +# Created by Chanhee Kim on 8/13/23. +# + +mac_old=(0 0xff00000005 0xff00000004 0xff0100000010 0xff010004 0xff00000009 0xff00000008 0xc000000b4 0xc000000cd 0xc000000b3 0xc000000e2 0xc000000ea 0xc000000e9) +mac_new=(0 0xff00000005 0xff00000004 0xff0100000010 0xc00000221 0xc000000cf 0x10000009b 0xc000000b4 0xc000000cd 0xc000000b3 0xc000000e2 0xc000000ea 0xc000000e9) + +this_mac=(${mac_new[@]}) # change based on "old" or "new" mac / magic keyboard layout + +fn_keys=(0 0x70000003a 0x70000003b 0x70000003c 0x70000003d 0x70000003e 0x70000003f 0x700000040 0x700000041 0x700000042 0x700000043 0x700000044 0x700000045 0x700000068 0x700000069 0x70000006a 0x70000006b 0x70000006c 0x70000006d 0x70000006e) +fn_bri_dec=0xff0100000021 # or 0xc00000070 +fn_bri_inc=0xff0100000020 # or 0xc0000006f +fn_missionc=0xff0100000010 +fn_spotl=0xff0100000001 # or 0xc00000221 +fn_dict=0xc000000cf +fn_dnd=0x10000009b +fn_rew=0xc000000b4 +fn_play=0xc000000cd +fn_fwd=0xc000000b3 +fn_mute=0xc000000e2 +fn_vol_inc=0xc000000ea +fn_vol_dec=0xc000000e9 +fn_kbd_inc=0xff00000008 +fn_kbd_dec=0xff00000009 +fn_launchp=0xff0100000004 +fn_globe=0xff0100000030 +fn_desktop=0x700000044 # or f11 +fn_num_div=0x700000054 +fn_num_mul=0x700000055 +fn_num_sub=0x700000056 +fn_num_add=0x700000057 +fn_num_enter=0x700000058 +fn_num1=0x700000059 +fn_num2=0x70000005a +fn_num3=0x70000005b +fn_num4=0x70000005c +fn_num5=0x70000005d +fn_num6=0x70000005e +fn_num7=0x70000005f +fn_num8=0x700000060 +fn_num9=0x700000061 +fn_num0=0x700000062 +fn_num_dot=0x700000063 +fn_num_equ=0x700000067 + +function help() { + echo "$LESS_TERMCAP_mb$0 $LESS_TERMCAP_md[command]$LESS_TERMCAP_me + where $LESS_TERMCAP_md[command]$LESS_TERMCAP_me is one of: + show display the current user key map + export output the current user key map for creating a LaunchAgent + reset reset user key map to default + default display the default key map (from ioreg) +$LESS_TERMCAP_mb$0 $LESS_TERMCAP_md[n=keycode ...]$LESS_TERMCAP_me + where ${LESS_TERMCAP_us}n$LESS_TERMCAP_ue is 1 to 12 for thefunction key, and + ${LESS_TERMCAP_us}keycode$LESS_TERMCAP_ue is a hex key code starting with 0x +$LESS_TERMCAP_mb$0 $LESS_TERMCAP_md[n=function ...]$LESS_TERMCAP_me + where ${LESS_TERMCAP_us}n$LESS_TERMCAP_ue is 1 to 12 for the function key, and + ${LESS_TERMCAP_us}function$LESS_TERMCAP_ue is one of: + bri_dec | bri_inc decrease / increase display brightness + kbd_dec | kbd_inc decrease / increase keyboard backlight brightness + missionc | launchp show mission control / launchpad + spotl | dict spotlight search / dictation (hold for Siri) + dnd | mute toggle do not disturb / mute + rew | play | fwd rewind / play or pause / fast-forward media + vol_dec | vol_inc decrease / increase volume + globe | desktop show emoji / desktop (same as F11) + num0 to num9 number pad keys, along with: + num_add | num_sub | num_mul | num_div | num_dot | num_equ | num_enter +" +} +function show() { + echo Current user key map + hidutil property -g UserKeyMapping +} +function reset() { + echo Reset user key map + hidutil property -s "{\"UserKeyMapping\":[]}" >/dev/null +} +function default() { + echo Show default key map + ioreg -l | grep -o "\"FnFunctionUsageMap\" = .*" +} +function export() { + x=$(hidutil property -g UserKeyMapping | sed -E "s/(HIDKeyboardModifierMappingDst) = (.*);/\"\1\": \2,/g;s/(HIDKeyboardModifierMappingSrc) = (.*);/\"\1\": \2/g;s/\(/[/;s/\)/]/") + echo ' + + + + Label + com.local.KeyRemapping + ProgramArguments + + /usr/bin/hidutil + property + --set + {"UserKeyMapping":'"$x"' + } + + RunAtLoad + + +' +} +function map() { + y="" + for x in "$@"; do + x=(${x//=/ }) + x0=${x[0]} + x1=${x[1]} + if [[ ${#x[@]} -eq 2 && ( $x0 == [1-9] || $x0 == 1[012]) ]]; then + fn=${this_mac[$x0]} + [[ "$fn" == "" ]] && echo "Error no such key F$x0" && exit -1 + if [[ "$x1" == f[1-9] || "$x1" == f1[0-9] ]]; then + kc=${x1:1} + kc=${fn_keys[$kc]} + [[ "$kc" == "" ]] && echo "Error mapping F$x0 [$fn] to unknown $x1" && exit -1 + echo "Mapping F$x0 [$fn] to HID $x1 [$kc]" + y="{\"HIDKeyboardModifierMappingSrc\":$fn,\"HIDKeyboardModifierMappingDst\":$kc},$y" + elif [[ "$kc" == 0x[0-9A-Fa-f]* && ( ${#kc} -ge 11 && ${#kc} -le 14 ) ]]; then + echo "Mapping F$x0 [$fn] to HID hex code [$kc]" + y="{\"HIDKeyboardModifierMappingSrc\":$fn,\"HIDKeyboardModifierMappingDst\":$kc},$y" + else + kc=fn_$x1 + kc=${!kc} + [[ "$kc" == "" ]] && echo "Error mapping F$x0 [$fn] to unknown $x1" && exit -1 + echo "Mapping F$x0 [$fn] to HID $x1 [$kc]" + y="{\"HIDKeyboardModifierMappingSrc\":$fn,\"HIDKeyboardModifierMappingDst\":$kc},$y" + fi + fi + hidutil property -s "{\"UserKeyMapping\":[${y%?}]}" >/dev/null + done +} +function kbd() { + map 4=kbd_dec 5=kbd_inc +} +if [[ ${#@} -eq 1 && "$1" != *=* ]]; then + [[ $(LC_ALL=C type -t "$1") == "function" && "$1" != "map" ]] && $1 && exit $? +elif [[ ${#@} -ge 1 ]]; then + map "$@" + exit $? +fi +help diff --git a/Box42/Scripts/sh/nodeInstall.sh b/Box42/Scripts/sh/nodeInstall.sh new file mode 100644 index 0000000..767a31a --- /dev/null +++ b/Box42/Scripts/sh/nodeInstall.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +#42Box: https://github.com/42Box +#Author: chanheki +#Date: 2023/08/10 + +# BOXY FOX +echo "" +echo "\033[38;5;208m Boxy Fox Node install" +echo "" +echo " ████████" +echo " ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒" +echo " ████ ██████" +echo " ██ ████" +echo " ██ ██" +echo " ██ ░░░░░░░░░░░░░░██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░██ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██ ██████ ██████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░████ ██████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░████ ████████████" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░████ ████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████" +echo "░░██ ░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒██▓▓▓▓" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██▒▒████░░░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░████░░░░░░░░░░░░░░████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░████░░░░░░░░░░██████████████░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░▒▒▒▒████░░░░░░██████▒▒▒▒████████░░░░░░░░░░░░░░████▒▒▒▒░░░░░░░░░░██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░████░░░░████░░░░░░██████████░░░░░░████░░░░░░░░░░ ░░░░██" +echo " ░░▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓████▓▓░░░░▒▒████████▓▓▓▓▓▓▓▓▒▒░░░░░░░░░░ ░░░░██" +echo " ░░██░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒██████░░░░░░▒▒▒▒██████▒▒▒▒░░░░░░░░ ░░░░░░░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒████░░░░░░████▒▒ ░░░░░░ ░░░░ ░░░░██" +echo " ░░▓▓▓▓░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▓▓▒▒▒▒░░ ░░░░░░░░░░░░ ░░░░██" +echo " ░░░░▓▓▓▓░░░░░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓██▒▒░░░░░░░░░░░░░░ ░░░░ ░░██" +echo " ████░░░░░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░░░░░ ░░░░░░ ██ ░░██" +echo " ████░░░░░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ░░░░▓▓▓▓▓▓▓▓██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░░░ ░░░░ ████ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ░░░░ ███▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ▒▒██ ░░░░ ▒▒▒▒ ░░██" +echo " ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ░░░░ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ████ ██ ██" +echo " ██ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██ ████ ██" +echo " ██████ ░░░░░░░░░░░░░░░░░░░░░░░░░░██░░░░░░ ██" +echo " ████░░████ ░░░░░░░░░░░░░░░░░░░░░░██░░░░ ░░░░░░ ████" +echo " ████░░██░░██████ ░░░░░░░░░░░░░░░░░░██░░░░ ░░░░ ████" +echo " ██░░██░░░░██████████ ░░░░░░░░░░░░░░██░░░░ ██████████" +echo " ██████████████████████ ░░░░░░░░░░██░░░░ ████████████████" +echo " ██████████ ████ ░░░░░░██░░░░ ██████████████████████" +echo " ████ ░░██░░ ████ ████████████████" +echo " ████ ██ ██████████ ██████████" +echo " ████ ██ ████████████████ ██████" +echo " ████ ██ ██████████████████████" +echo " ██████ ████████████████" +echo " ██████████" +echo " ░░██████░░" +echo "" + + +export N_PREFIX=/goinfre +curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s lts +echo "# bin folder for node.js">>~/.zshrc +echo 'export PATH="$PATH:$HOME/bin"' >> ~/.zshrc +export PATH=/goinfre/bin:$PATH +ln -s /goinfre/bin ~/bin + +echo "Download Complete" From 12a26bb4c4946126e5de2dc3f38d80118c4c50eb Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 14 Aug 2023 05:45:00 +0900 Subject: [PATCH 13/55] =?UTF-8?q?refactor(Remove=F0=9F=A7=B9):=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/BoxButtonHandler.swift | 16 --- Box42/Box/BoxModel.swift | 22 ---- Box42/Box/BoxViewController.swift | 159 --------------------------- Box42/Box/BoxViewModel.swift | 29 ----- Box42/Box/View/BoxButtonView.swift | 123 --------------------- Box42/Box/View/BoxView.swift | 101 ----------------- Box42/URL/URLModel.swift | 46 -------- Box42/Window/BoxWindowController.xib | 31 ------ 8 files changed, 527 deletions(-) delete mode 100644 Box42/Box/BoxButtonHandler.swift delete mode 100644 Box42/Box/BoxModel.swift delete mode 100644 Box42/Box/BoxViewController.swift delete mode 100644 Box42/Box/BoxViewModel.swift delete mode 100644 Box42/Box/View/BoxButtonView.swift delete mode 100644 Box42/Box/View/BoxView.swift delete mode 100644 Box42/URL/URLModel.swift delete mode 100644 Box42/Window/BoxWindowController.xib diff --git a/Box42/Box/BoxButtonHandler.swift b/Box42/Box/BoxButtonHandler.swift deleted file mode 100644 index f79d076..0000000 --- a/Box42/Box/BoxButtonHandler.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// BoxButtonHandler.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa - -class BoxButtonHandler { - var clickAction: ((NSButton) -> Void)? - - @objc func buttonClicked(_ sender: NSButton) { - clickAction?(sender) - } -} diff --git a/Box42/Box/BoxModel.swift b/Box42/Box/BoxModel.swift deleted file mode 100644 index 686ced2..0000000 --- a/Box42/Box/BoxModel.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// BoxViewModel.swift -// Box42 -// -// Created by Chan on 2023/08/11. -// - -import Cocoa - -struct BoxViewSize { - var halfSize: (width: CGFloat, height: CGFloat)! - var size: (width: CGFloat, height: CGFloat)! - var buttonGroupSize: (width: CGFloat, height: CGFloat)! - var viewStack: [NSView?] - - init() { - halfSize = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) - size = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) - buttonGroupSize = (CGFloat(132), NSScreen.customScreenSize.y) - viewStack = [NSView()] - } -} diff --git a/Box42/Box/BoxViewController.swift b/Box42/Box/BoxViewController.swift deleted file mode 100644 index 784840c..0000000 --- a/Box42/Box/BoxViewController.swift +++ /dev/null @@ -1,159 +0,0 @@ -// -// BoxViewController.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Cocoa -import AppKit -import WebKit - -class BoxViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - var boxView: BoxButtonView! - var boxVM: BoxViewModel! - var wvc = WebViewController() - let preferencesVC = PreferencesViewController() - - private var webView: WKWebView! - - override func loadView() { - boxView = BoxButtonView() - boxVM = BoxViewModel() - } - - override func viewDidLoad() { - super.viewDidLoad() - view.window?.styleMask.insert(.resizable) - view.window?.makeFirstResponder(self) - - webViewInit() - wvc.loadWebViewInit() - configureButton() - } - - @objc - func doubleClickBtn(sender: NSButton) { - WebViewList.shared.list[sender.title]!.reload() - } - - @objc - func clickBtn(sender: NSButton) { - guard let clickCount = NSApp.currentEvent?.clickCount else { return } - if sender.title == "Preferences" { - boxView.hostingViewGroup.subviews.removeAll() - boxView.hostingViewGroup.addSubview(preferencesVC.view) - preferencesVC.viewDidAppear() - setAutoLayout(from: preferencesVC.view, to: boxView.hostingViewGroup) - return - } - if clickCount == 2 { - WebViewList.shared.list[sender.title]!.reload() - print("Dobule Click") - } else if clickCount > 2 { - let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) - WebViewList.shared.list[sender.title]!.load(rqURL) - print("Triple Click") - } else if clickCount < 2 { - boxView.hostingViewGroup.subviews.removeAll() - boxView.hostingViewGroup.addSubview(WebViewList.shared.list[sender.title]!) - WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true - WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true - WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() - setAutoLayout(from: WebViewList.shared.list[sender.title]!, to: boxView.hostingViewGroup) - } - } - - @objc - func pin(_ sender: NSSwitch) { - StateManager.shared.setToggleIsPin() - print(sender.state) - } - - func webViewInit() { - boxVM.setUpURLdict() - webView = wvc.addWebView() - boxView.hostingViewGroup.addSubview(webView) - setAutoLayout(from: webView, to: boxView.hostingViewGroup) - let request = URLRequest(url: boxVM.URLdict["home"]!) - DispatchQueue.main.async { - self.webView.load(request) - } - } - - public func setAutoLayout(from: NSView, to: NSView) { - from.translatesAutoresizingMaskIntoConstraints = false - to.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true - view.layout() - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - print(message.name) - } - - func configureButton() { - boxView.createHomeButton(clickAction: clickBtn) - for (name, _) in boxVM.webViewURL.URLstring { - boxView.createButton(name, clickAction: clickBtn) - } - boxView.divide() - boxView.preferencesButton(clickAction: clickBtn) - boxView.createQuitButton() - boxView.createPinButton(clickAction: clickBtn) - } -} - -extension BoxViewController { - static func freshController() -> BoxViewController { - let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) - let identifier = NSStoryboard.SceneIdentifier("Main") - - guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? BoxViewController else { - fatalError("Story Board Not Found") - } - return viewcontroller - } -} - -extension BoxViewController { - override func keyDown(with event: NSEvent) { - print(event.keyCode) - if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. - print("escape") - } else { - super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 - } - - if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { - // 복사 동작 처리 - webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in - if let error = error { - print("Copy error: \(error)") - } else { - print("Copy success") - } - } - } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { - // 붙여넣기 동작 처리 - let pasteboard = NSPasteboard.general - if let pasteString = pasteboard.string(forType: .string) { - let escapedPasteString = pasteString.escapedForJavaScript - webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in - if let error = error { - print("Paste error: \(error)") - } else { - print("Paste success") - } - } - } - } else { - super.keyDown(with: event) // 기본 키 이벤트 처리 - } - } -} diff --git a/Box42/Box/BoxViewModel.swift b/Box42/Box/BoxViewModel.swift deleted file mode 100644 index 3fbd9ff..0000000 --- a/Box42/Box/BoxViewModel.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// URLViewModel.swift -// Box42 -// -// Created by Chanhee Kim on 8/9/23. -// - -import Foundation -import Combine - -// CRUD 4가지 형태의 데이터 가공 create, read, update, delete -class BoxViewModel: ObservableObject { - var webViewURL: URLModels - @Published var URLdict: [String: URL] - - init() { - self.webViewURL = URLModels(info: [URLModel(name: "home", url: "https://42box.github.io/front-end/")]) - self.URLdict = [String: URL]() - } - - func setUpURLdict() { -// for urlModel in webViewURL.info { -// URLdict[urlModel.name] = URL(string: urlModel.url) -// } - for urlModel in webViewURL.URLstring { - URLdict[urlModel.0] = URL(string: urlModel.1) - } - } -} diff --git a/Box42/Box/View/BoxButtonView.swift b/Box42/Box/View/BoxButtonView.swift deleted file mode 100644 index 37a9a6f..0000000 --- a/Box42/Box/View/BoxButtonView.swift +++ /dev/null @@ -1,123 +0,0 @@ -// -// BoxButtonView.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa - -class BoxButtonView: BoxView { - var topAnchorDistance: CGFloat = 0 - - func createButton(_ title: String, clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - - button.title = title - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 30 - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createHomeButton(clickAction: @escaping (NSButton) -> Void) { - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: handler, action: #selector(handler.buttonClicked(_:))) - - button.translatesAutoresizingMaskIntoConstraints = false - button.isBordered = false - button.imagePosition = .imageOnly - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 80 - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createQuitButton() { - let button = NSButton() - button.title = "Quit Box" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(NSApplication.terminate(_:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -10).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createPinButton(clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - button.title = "Pin Box" - button.setButtonType(.toggle) - button.contentTintColor = .orange - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -50).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func preferencesButton(clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - button.title = "Preferences" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -90).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - -} diff --git a/Box42/Box/View/BoxView.swift b/Box42/Box/View/BoxView.swift deleted file mode 100644 index c20ca54..0000000 --- a/Box42/Box/View/BoxView.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// BoxView.swift -// Box42 -// -// Created by Chan on 2023/03/17. -// - -import Cocoa - -class BoxView: NSView { - var buttonBoxGroup : NSView! - var buttonViewGroup : NSView! - var hostingViewGroup : NSView! - var divider : NSBox! - var pinSwitch : NSSwitch! - var boxModel = BoxViewSize() - - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - commonInit() - viewInit() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - commonInit() - viewInit() - } - - private func commonInit() { - buttonBoxGroup = NSView() - buttonViewGroup = NSView() - hostingViewGroup = NSView() - divider = NSBox() - pinSwitch = NSSwitch() - - // Pan Gesture Recognizer를 추가합니다. - let panRecognizer = NSPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) - addGestureRecognizer(panRecognizer) - } - - func viewInit() { - self.boxViewSizeInit() - self.buttonBoxGroupInit() - self.divide() - } - - func boxViewSizeInit() { - self.frame.size.width = boxModel.size.width - self.frame.size.height = boxModel.size.height - - hostingViewGroup.frame.size.width = boxModel.size.width - boxModel.buttonGroupSize.width - hostingViewGroup.frame.size.height = boxModel.size.height - - buttonViewGroup.frame.size.width = boxModel.buttonGroupSize.width - buttonViewGroup.frame.size.height = boxModel.buttonGroupSize.height - } - - func divide() { - divider.translatesAutoresizingMaskIntoConstraints = false - divider.bottomAnchor.constraint(equalTo: buttonBoxGroup.bottomAnchor, constant: -40).isActive = true - } - - func buttonBoxGroupInit() { - self.buttonBoxGroup = NSView(frame: NSRect(x: 0, y: 0, width: boxModel.buttonGroupSize.width, height: boxModel.buttonGroupSize.height)) - self.buttonBoxGroup.frame.size.width = boxModel.buttonGroupSize.width - self.buttonBoxGroup.frame.size.height = boxModel.buttonGroupSize.height - self.buttonViewGroup.addSubview(self.buttonBoxGroup) - - setAutoLayout(from: self.buttonBoxGroup, to: self.buttonViewGroup) - } - - func setAutoLayout(from: NSView, to: NSView) { - from.translatesAutoresizingMaskIntoConstraints = false - to.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true - self.layout() - } -} - -extension BoxView { - @objc private func handlePanGesture(_ recognizer: NSPanGestureRecognizer) { - guard let view = recognizer.view else { return } - - // 사용자가 드래그한 변화량을 가져옵니다. - let translation = recognizer.translation(in: view) - - // 드래그로 인한 크기 변화를 계산합니다. - let newWidth = view.frame.width + translation.x - let newHeight = view.frame.height + translation.y - - // 크기를 적용합니다. - view.setFrameSize(NSSize(width: newWidth, height: newHeight)) - - // 변화량을 리셋합니다. - recognizer.setTranslation(.zero, in: view) - } -} diff --git a/Box42/URL/URLModel.swift b/Box42/URL/URLModel.swift deleted file mode 100644 index 9763fce..0000000 --- a/Box42/URL/URLModel.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// URLModel.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Foundation - -struct URLModel { - var id: UUID - var name: String - var url: String - - init(name: String, url: String) { - self.id = UUID() - self.name = name - self.url = url - } -} - -struct URLModels { - var info: [URLModel] - - // Network logic - let URLstring: [(String, String)] = [ - ("home", "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"), - ("E-Library", "https://42seoul.dkyobobook.co.kr/main.ink"), - ("24Hane", "https://24hoursarenotenough.42seoul.kr"), - ("80000Coding", "https://80000coding.oopy.io"), - ("where42", "https://www.where42.kr"), - ("cabi", "https://cabi.42seoul.io/"), - ("42gg", "https://42gg.kr/"), - ("textart", "https://textart.sh/") - ] - - mutating func urlSetup() { - URLstring.forEach { (name, url) in - info.append(URLModel(name: name, url: url)) - } - } -} diff --git a/Box42/Window/BoxWindowController.xib b/Box42/Window/BoxWindowController.xib deleted file mode 100644 index 30df79a..0000000 --- a/Box42/Window/BoxWindowController.xib +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From fe7e72e3eb3d53710a260c269a515b83954311e6 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 14 Aug 2023 05:46:15 +0900 Subject: [PATCH 14/55] =?UTF-8?q?refactor(=E2=9C=A8):=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 124 ++++++++++ Box42/Box/BoxButtonView.swift | 124 ++++++++++ Box42/Box/BoxButtonViewGroup.swift | 223 ++++++++++++++++++ Box42/Box/BoxContentsViewGroup.swift | 35 +++ Box42/Login/LoginViewController.swift | 44 ++++ Box42/Main/BoxButtonHandler.swift | 34 +++ Box42/Main/BoxViewController.swift | 57 +++++ Box42/Main/BoxViewModel.swift | 14 ++ Box42/Menubar/MenubarViewController.swift | 48 ++-- Box42/Shared/BoxSizeManager.swift | 30 +++ Box42/WebView/URL/URLModel.swift | 46 ++++ Box42/WebView/WebViewController.swift | 52 +++- Box42/WebView/WebViewModel.swift | 23 ++ Box42/Window/BoxWindowController.swift | 29 ++- 14 files changed, 853 insertions(+), 30 deletions(-) create mode 100644 Box42/Box/BoxBaseContainerViewController.swift create mode 100644 Box42/Box/BoxButtonView.swift create mode 100644 Box42/Box/BoxButtonViewGroup.swift create mode 100644 Box42/Box/BoxContentsViewGroup.swift create mode 100644 Box42/Login/LoginViewController.swift create mode 100644 Box42/Main/BoxButtonHandler.swift create mode 100644 Box42/Main/BoxViewController.swift create mode 100644 Box42/Main/BoxViewModel.swift create mode 100644 Box42/Shared/BoxSizeManager.swift create mode 100644 Box42/WebView/URL/URLModel.swift diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift new file mode 100644 index 0000000..8385287 --- /dev/null +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -0,0 +1,124 @@ +// +// BoxBaseContainerViewController.swift +// Box42 +// +// Created by Chan on 2023/03/17. +// + +import Cocoa + +class BoxBaseContainerViewController: NSViewController { + var buttonGroup : BoxButtonViewGroup! + var contentGroup : BoxContentsViewGroup! + + override func loadView() { + self.view = NSView() // 뷰 컨트롤러의 뷰 설정 + buttonGroup = BoxButtonViewGroupInit() + contentGroup = BoxContentsViewGroup() + panGestureInit() + viewInit() + } + + func BoxButtonViewGroupInit() -> BoxButtonViewGroup { + let buttonGroup = BoxButtonViewGroup { sender in + // 버튼을 클릭할 때 실행할 코드 + self.clickBtn(sender: sender) + } + view.addSubview(buttonGroup) + return buttonGroup + } + + func clickBtn(sender: NSButton) { + guard let clickCount = NSApp.currentEvent?.clickCount else { return } + if sender.title == "Preferences" { +// boxView.contentGroup.subviews.removeAll() +// boxView.contentGroup.addSubview(preferencesVC.view) +// preferencesVC.viewDidAppear() + return + } + if clickCount == 2 { + WebViewList.shared.list[sender.title]!.reload() + print("Dobule Click") + } else if clickCount > 2 { +// let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) +// WebViewList.shared.list[sender.title]!.load(rqURL) + print("Triple Click") + } else if clickCount < 2 { +// boxView.contentGroup.subviews.removeAll() +// boxView.contentGroup.addSubview(WebViewList.shared.list[sender.title]!) + WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true + WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true + WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() + } + } + + private func panGestureInit() { + let panRecognizer = NSPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) + self.view.addGestureRecognizer(panRecognizer) // 뷰 컨트롤러의 뷰에 제스처 추가 + } + + func viewInit() { + self.boxViewSizeInit() + self.buttonBoxGroupInit() + self.contentsGroupInit() + + // buttonGroup과 contentGroup을 self에 추가합니다. + view.addSubview(buttonGroup) + view.addSubview(contentGroup) + + // buttonGroup 오토레이아웃 설정 + buttonGroup.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + buttonGroup.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), + buttonGroup.topAnchor.constraint(equalTo: self.view.topAnchor), + buttonGroup.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), + buttonGroup.widthAnchor.constraint(equalToConstant: BoxSizeManager.shared.buttonGroupSize.width) + ]) + + // contentGroup 오토레이아웃 설정 + contentGroup.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + contentGroup.leadingAnchor.constraint(equalTo: buttonGroup.trailingAnchor), + contentGroup.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), + contentGroup.topAnchor.constraint(equalTo: self.view.topAnchor), + contentGroup.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) + ]) + } + + func boxViewSizeInit() { + self.view.frame.size.width = BoxSizeManager.shared.size.width + self.view.frame.size.height = BoxSizeManager.shared.size.height + } + + func contentsGroupInit() { + self.contentGroup.frame.size.width = BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width + self.contentGroup.frame.size.height = BoxSizeManager.shared.size.height + } + + func buttonBoxGroupInit() { + self.buttonGroup.frame.size.width = BoxSizeManager.shared.buttonGroupSize.width + self.buttonGroup.frame.size.height = BoxSizeManager.shared.buttonGroupSize.height + } +} + +extension BoxBaseContainerViewController { + // 추후 논의. 내부 panGesture로 View크기 증감 + @objc private func handlePanGesture(_ recognizer: NSPanGestureRecognizer) { + guard let view = recognizer.view else { return } + + // 사용자가 드래그한 변화량을 가져옵니다. + let translation = recognizer.translation(in: view) + + // 드래그로 인한 크기 변화를 계산합니다. + let newWidth = view.frame.width + translation.x + let newHeight = view.frame.height + translation.y + + // 크기를 적용합니다. + view.setFrameSize(NSSize(width: newWidth, height: newHeight)) + + // 변화량을 리셋합니다. + recognizer.setTranslation(.zero, in: view) + + print(newWidth, newHeight) + } +} diff --git a/Box42/Box/BoxButtonView.swift b/Box42/Box/BoxButtonView.swift new file mode 100644 index 0000000..fda1196 --- /dev/null +++ b/Box42/Box/BoxButtonView.swift @@ -0,0 +1,124 @@ +// +// BoxButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxButtonViewGroup: NSView { + // var boxButtonGroup = NSView?.self + var topAnchorDistance: CGFloat = 0 + + func createButton(_ title: String, clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + + button.title = title + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 30 + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createHomeButton(clickAction: @escaping (NSButton) -> Void) { + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: handler, action: #selector(handler.buttonClicked(_:))) + + button.translatesAutoresizingMaskIntoConstraints = false + button.isBordered = false + button.imagePosition = .imageOnly + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true + topAnchorDistance += 80 + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createQuitButton() { + let button = NSButton() + button.title = "Quit Box" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(NSApplication.terminate(_:)) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -10).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func createPinButton(clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + button.title = "Pin Box" + button.setButtonType(.toggle) + button.contentTintColor = .orange + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -50).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + + func preferencesButton(clickAction: @escaping (NSButton) -> Void) { + let button = NSButton() + button.title = "Preferences" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + let handler = BoxButtonHandler() + handler.clickAction = clickAction + + button.target = handler + button.action = #selector(handler.buttonClicked(_:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.buttonBoxGroup.addSubview(button) + + button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -90).isActive = true + button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true + } + +} diff --git a/Box42/Box/BoxButtonViewGroup.swift b/Box42/Box/BoxButtonViewGroup.swift new file mode 100644 index 0000000..4b51f0d --- /dev/null +++ b/Box42/Box/BoxButtonViewGroup.swift @@ -0,0 +1,223 @@ +// +// BoxButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxButtonViewGroup: NSView { + var boxVM: WebViewModel! = WebViewModel() + var divider : NSBox = NSBox() + var pinSwitch : NSSwitch = NSSwitch() + var clickAction: ((NSButton) -> Void)? + var lastAddedButton: NSView? + + init(clickAction: @escaping (NSButton) -> Void) { + self.clickAction = clickAction + super.init(frame: BoxSizeManager.shared.buttonGroupSizeNSRect) + +// self.wantsLayer = true + setupButtons() + divide() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ dirtyRect: NSRect) { + // 뷰의 커스텀 렌더링에 사용됨. + } + + override func layout() { + // layout(): 뷰의 서브뷰들이 리사이징될 때 호출됩니다. 레이아웃을 조정하는 데 사용됩니다. + } + + private func setupButtons() { + createHomeButton() + for (name, _) in boxVM.webViewURL.URLstring { + self.createButton(name) + } + preferencesButton() + createQuitButton() + createPinButton() + } + + @objc private func clickBtn(sender: NSButton) { + clickAction?(sender) // 클로저 실행 + } + + private func createButton(_ title: String) { + let button = NSButton() + + button.title = title + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + button.target = self + button.action = #selector(clickBtn(sender:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + super.addSubview(button) + + NSLayoutConstraint.activate([ + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), + // 이전 버튼의 bottom anchor와 연결 + button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), + button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), + button.heightAnchor.constraint(equalToConstant: 30) + ]) + + lastAddedButton = button + } + +// func createHomeButton() { +// let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) +// +// button.translatesAutoresizingMaskIntoConstraints = false +// button.isBordered = false +// button.imagePosition = .imageOnly +// +// super.addSubview(button) +// +// NSLayoutConstraint.activate([ +// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), +// // 이전 버튼의 bottom anchor와 연결 +// button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), +// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), +// button.heightAnchor.constraint(equalToConstant: 30) +// ]) +// +// lastAddedButton = button +// } + + func createHomeButton() { + let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) + super.addSubview(button) + + button.translatesAutoresizingMaskIntoConstraints = false + button.isBordered = false + button.imagePosition = .imageOnly + + +// NSLayoutConstraint.activate([ +// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), +// button.topAnchor.constraint(equalTo: self.topAnchor, constant: 0), +// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), +//// button.heightAnchor.constraint(equalToConstant: 30) +// ]) + + NSLayoutConstraint.activate([ + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), // 좌측 간격을 100에서 20으로 변경 + button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), // 우측 간격을 80에서 20으로 변경 + button.heightAnchor.constraint(equalToConstant: 30) + ]) + + lastAddedButton = nil // home 버튼 이후의 버튼들이 상단에 연결되지 않도록 설정 + } + + + +// func createQuitButton() { +// let button = NSButton() +// button.title = "Quit Box" +// button.setButtonType(.momentaryLight) +// +// button.translatesAutoresizingMaskIntoConstraints = false +// button.action = #selector(NSApplication.terminate(_:)) +// button.isBordered = true +// button.bezelStyle = .roundRect +// button.showsBorderOnlyWhileMouseInside = true +// +// self.addSubview(button) +// +// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true +// button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true +// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true +// } + + func createQuitButton() { + let button = NSButton() + button.title = "Quit Box" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + button.action = #selector(NSApplication.terminate(_:)) + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + self.addSubview(button) + + NSLayoutConstraint.activate([ + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), + button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), // 이 부분 수정 + button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), + button.heightAnchor.constraint(equalToConstant: 30) + ]) + + lastAddedButton = button // 이 부분 추가 + } + + + func createPinButton() { + let button = NSButton() + button.title = "Pin Box" + button.setButtonType(.toggle) + button.contentTintColor = .orange + button.translatesAutoresizingMaskIntoConstraints = false + + button.target = self + button.action = #selector(clickBtn(sender:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + self.addSubview(button) + + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50).isActive = true + button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + } + + func preferencesButton() { + let button = NSButton() + button.title = "Preferences" + button.setButtonType(.momentaryLight) + + button.translatesAutoresizingMaskIntoConstraints = false + + button.target = self + button.action = #selector(clickBtn(sender:)) + + button.isBordered = true + button.bezelStyle = .roundRect + button.showsBorderOnlyWhileMouseInside = true + + self.addSubview(button) + + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true + button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -90).isActive = true + button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + } + + func divide() { + divider.boxType = .separator + divider.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(divider) + NSLayoutConstraint.activate([ + divider.leadingAnchor.constraint(equalTo: self.leadingAnchor), + divider.trailingAnchor.constraint(equalTo: self.trailingAnchor), + divider.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -40), + divider.heightAnchor.constraint(equalToConstant: 1) + ]) + } + +} diff --git a/Box42/Box/BoxContentsViewGroup.swift b/Box42/Box/BoxContentsViewGroup.swift new file mode 100644 index 0000000..ed20f4a --- /dev/null +++ b/Box42/Box/BoxContentsViewGroup.swift @@ -0,0 +1,35 @@ +// +// BoxContentsViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/13/23. +// + +import Cocoa +import WebKit + +class BoxContentsViewGroup: NSView { + var webVC: WebViewController? + var webView: WKWebView! + + init() { + let webVC = WebViewController(nibName: nil, bundle: nil) + + super.init(frame: NSRect(x: 0, y: 0, width: BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width, height: BoxSizeManager.shared.buttonGroupSize.height)) + + self.wantsLayer = true + webVC.view.frame = self.bounds + self.addSubview(webVC.view) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + // Drawing code here. + } +} + diff --git a/Box42/Login/LoginViewController.swift b/Box42/Login/LoginViewController.swift new file mode 100644 index 0000000..6020ea4 --- /dev/null +++ b/Box42/Login/LoginViewController.swift @@ -0,0 +1,44 @@ +// +// LoginViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/13/23. +// + +import Cocoa + +class LoginViewController: NSViewController { + var loginContainerView: NSView = { + let loginView = NSView() + loginView.translatesAutoresizingMaskIntoConstraints = false + loginView.wantsLayer = true + loginView.layer?.backgroundColor = NSColor.gray.cgColor + return loginView + }() + + override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nil, bundle: nil) // 여기에서 nibName을 nil로 전달 + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + self.view = NSView() // 기본 뷰 설정 + } + + override func viewDidLoad() { + super.viewDidLoad() + // Do view setup here. + view.addSubview(loginContainerView) + + // loginContainerView가 뷰 컨트롤러의 전체 뷰 영역을 차지하도록 제약 추가 + NSLayoutConstraint.activate([ + loginContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + loginContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + loginContainerView.topAnchor.constraint(equalTo: view.topAnchor), + loginContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } +} diff --git a/Box42/Main/BoxButtonHandler.swift b/Box42/Main/BoxButtonHandler.swift new file mode 100644 index 0000000..2c5440c --- /dev/null +++ b/Box42/Main/BoxButtonHandler.swift @@ -0,0 +1,34 @@ +// +// BoxButtonHandler.swift +// Box42 +// +// Created by Chanhee Kim on 8/11/23. +// + +import Cocoa + +class BoxButtonHandler { + func clickBtn(sender: NSButton) {} +// guard let clickCount = NSApp.currentEvent?.clickCount else { return } +// if sender.title == "Preferences" { +//// boxView.contentGroup.subviews.removeAll() +//// boxView.contentGroup.addSubview(preferencesVC.view) +//// preferencesVC.viewDidAppear() +// return +// } +// if clickCount == 2 { +// WebViewList.shared.list[sender.title]!.reload() +// print("Dobule Click") +// } else if clickCount > 2 { +//// let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) +//// WebViewList.shared.list[sender.title]!.load(rqURL) +// print("Triple Click") +// } else if clickCount < 2 { +//// boxView.contentGroup.subviews.removeAll() +//// boxView.contentGroup.addSubview(WebViewList.shared.list[sender.title]!) +// WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true +// WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true +// WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() +// } +// } +} diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift new file mode 100644 index 0000000..3d378fa --- /dev/null +++ b/Box42/Main/BoxViewController.swift @@ -0,0 +1,57 @@ +// +// BoxViewController.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import Cocoa +import AppKit +import WebKit + +class BoxViewController: NSViewController { + + var boxView: BoxBaseContainerViewController! = BoxBaseContainerViewController() + + let preferencesVC = PreferencesViewController() + let buttonHandler = BoxButtonHandler() + weak var menubarVCDelegate: MenubarViewControllerDelegate? + + + override func loadView() { + self.view = boxView.view + } + + override func viewDidLoad() { + super.viewDidLoad() + menubarVCDelegate = (NSApplication.shared.delegate as? AppDelegate)?.menubarController + } + + + @objc + func doubleClickBtn(sender: NSButton) { + WebViewList.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) + } +} + +extension BoxViewController { + override func keyDown(with event: NSEvent) { + print(event.keyCode) + if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. + print("escape") + menubarVCDelegate?.toggleWindow(sender: nil) + } else { + super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 + } + } +} diff --git a/Box42/Main/BoxViewModel.swift b/Box42/Main/BoxViewModel.swift new file mode 100644 index 0000000..3ae31fd --- /dev/null +++ b/Box42/Main/BoxViewModel.swift @@ -0,0 +1,14 @@ +// +// URLViewModel.swift +// Box42 +// +// Created by Chanhee Kim on 8/9/23. +// + +import Foundation +import Combine + +// CRUD 4가지 형태의 데이터 가공 create, read, update, delete +class BoxViewModel: ObservableObject { + // Box View Model은 전체적인 View Model을 담당하게 될것. +} diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index b381e1c..0165ed7 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -24,7 +24,7 @@ class MenubarViewController: NSWorkspace { func menubarViewControllerStart() { self.menubarStartRunning() self.buttonActionInit() - self.popoverHandler() + self.popoverCoentViewInit() self.startEventMonitoring() } @@ -57,6 +57,11 @@ class MenubarViewController: NSWorkspace { statusBarVM.statusBar.statusItem.button?.action = #selector(togglePopover(_:)) statusBarVM.statusBar.statusItem.button?.target = self } + + func popoverCoentViewInit() { + let boxViewController = BoxViewController(nibName: nil, bundle: nil) + popover.contentViewController = boxViewController + } func setupEventMonitor() -> EventMonitor { return EventMonitor(mask: [.leftMouseDown, .rightMouseDown, .otherMouseDown]) { [weak self] event in @@ -66,7 +71,7 @@ class MenubarViewController: NSWorkspace { } } else if let strongSelf = self, !strongSelf.popover.isShown { if event?.buttonNumber == 2 { - strongSelf.showPopover(sender: event) + strongSelf.popoverHandler(sender: event) } } } @@ -76,32 +81,37 @@ class MenubarViewController: NSWorkspace { if popover.isShown { closePopover(sender: sender) } else { - showPopover(sender: sender) + popoverHandler(sender: sender) } } - func popoverHandler() { - popover.contentViewController = BoxViewController.freshController() - } - - func showPopover(sender: Any?) { + func popoverHandler(sender: Any?) { if let event = sender as? NSEvent { if event.type == .otherMouseDown { - self.showWindow(sender: sender) + self.toggleWindow(sender: sender) } } else if let button = statusBarVM.statusBar.statusItem.button { popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) } } - - func showWindow(sender: Any?) { - boxWindowController?.close() - boxWindowController = BoxWindowController(windowNibName: NSNib.Name("BoxWindowController")) + func closePopover(sender: Any?) { + popover.performClose(sender) + } +} + +extension MenubarViewController: MenubarViewControllerDelegate { + func toggleWindow(sender: Any?) { + StateManager.shared.setToggleIsShowWindow(); + if StateManager.shared.getToggleIsShowWindow() == false { + boxWindowController?.close() + print("close") + return + } + boxWindowController = BoxWindowController(window: nil) // status bar 버튼의 위치를 얻어옵니다. if let button = statusBarVM.statusBar.statusItem.button, - let screenFrame = NSScreen.main?.frame, let window = boxWindowController?.window { let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect @@ -114,13 +124,13 @@ class MenubarViewController: NSWorkspace { // 윈도우의 위치를 설정 window.setFrameOrigin(desiredPosition) + window.level = .floating } - boxWindowController?.contentViewController = BoxViewController.freshController() + boxWindowController?.showWindow(sender) } +} - - func closePopover(sender: Any?) { - popover.performClose(sender) - } +protocol MenubarViewControllerDelegate: AnyObject { + func toggleWindow(sender: Any?) } diff --git a/Box42/Shared/BoxSizeManager.swift b/Box42/Shared/BoxSizeManager.swift new file mode 100644 index 0000000..ed665bf --- /dev/null +++ b/Box42/Shared/BoxSizeManager.swift @@ -0,0 +1,30 @@ +// +// BoxSizeManager.swift +// Box42 +// +// Created by Chan on 2023/08/11. +// + +import Cocoa + +struct BoxSizeManager { + static let shared = BoxSizeManager() + + var halfSize: (width: CGFloat, height: CGFloat)! + var size: (width: CGFloat, height: CGFloat)! + var buttonGroupSize: (width: CGFloat, height: CGFloat)! + var viewStack: [NSView?] + var boxViewSizeNSRect: NSRect + var boxViewSizeNSSize: NSSize + var buttonGroupSizeNSRect: NSRect + + init() { + halfSize = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) + size = (NSScreen.customScreenSize.x, NSScreen.customScreenSize.y) + buttonGroupSize = (CGFloat(132), NSScreen.customScreenSize.y) + 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) + } +} diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift new file mode 100644 index 0000000..9763fce --- /dev/null +++ b/Box42/WebView/URL/URLModel.swift @@ -0,0 +1,46 @@ +// +// URLModel.swift +// Box42 +// +// Created by Chan on 2023/03/16. +// + +import Foundation + +struct URLModel { + var id: UUID + var name: String + var url: String + + init(name: String, url: String) { + self.id = UUID() + self.name = name + self.url = url + } +} + +struct URLModels { + var info: [URLModel] + + // Network logic + let URLstring: [(String, String)] = [ + ("home", "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"), + ("E-Library", "https://42seoul.dkyobobook.co.kr/main.ink"), + ("24Hane", "https://24hoursarenotenough.42seoul.kr"), + ("80000Coding", "https://80000coding.oopy.io"), + ("where42", "https://www.where42.kr"), + ("cabi", "https://cabi.42seoul.io/"), + ("42gg", "https://42gg.kr/"), + ("textart", "https://textart.sh/") + ] + + mutating func urlSetup() { + URLstring.forEach { (name, url) in + info.append(URLModel(name: name, url: url)) + } + } +} diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 984f888..51028b9 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -9,9 +9,18 @@ import Cocoa import WebKit class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { - var URLVM = BoxViewModel() + var URLVM = WebViewModel() + var webView: WKWebView! + + override func loadView() { + self.webView = addWebView() + self.view = webView + loadWebViewInit() + webViewInit() + } func loadWebViewInit() { + URLVM.setUpURLdict() for (key, value) in URLVM.URLdict { let wkWebView = addWebView() WebViewList.shared.list[key] = wkWebView @@ -22,6 +31,14 @@ class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, } } + func webViewInit() { + let request = URLRequest(url: URLVM.URLdict["home"]!) +// let request = URLRequest(url: URL(fileURLWithPath: "https://github.com/CHANhihi")) + DispatchQueue.main.async { + self.webView.load(request) + } + } + func addWebView() -> WKWebView { let preferences = WKPreferences() preferences.javaScriptEnabled = true @@ -58,3 +75,36 @@ class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, } } +extension WebViewController { + override func keyDown(with event: NSEvent) { + print(event.keyCode) + + if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { + // 복사 동작 처리 + webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in + if let error = error { + print("Copy error: \(error)") + } else { + print("Copy success") + } + } + } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || + (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { + // 붙여넣기 동작 처리 + let pasteboard = NSPasteboard.general + if let pasteString = pasteboard.string(forType: .string) { + let escapedPasteString = pasteString.escapedForJavaScript + webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in + if let error = error { + print("Paste error: \(error)") + } else { + print("Paste success") + } + } + } + } else { + super.keyDown(with: event) // 기본 키 이벤트 처리 + } + } +} diff --git a/Box42/WebView/WebViewModel.swift b/Box42/WebView/WebViewModel.swift index 4d6574b..b3f64ad 100644 --- a/Box42/WebView/WebViewModel.swift +++ b/Box42/WebView/WebViewModel.swift @@ -17,3 +17,26 @@ class WebViewList { list = [:] } } + +// CRUD 4가지 형태의 데이터 가공 create, read, update, delete +class WebViewModel: ObservableObject { + var webViewURL: URLModels + @Published var URLdict: [String: URL] + + init() { + self.webViewURL = URLModels(info: [URLModel(name: "home", url: "https://42box.github.io/front-end/")]) + self.URLdict = [String: URL]() + } + + func setUpURLdict() { +// for urlModel in webViewURL.info { +// URLdict[urlModel.name] = URL(string: urlModel.url) +// } + for urlModel in webViewURL.URLstring { + URLdict[urlModel.0] = URL(string: urlModel.1) + } + } + + +} + diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index 4c609b3..affb589 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -8,19 +8,28 @@ import Cocoa class BoxWindowController: NSWindowController { + + override init(window: NSWindow?) { + let contentRect = BoxSizeManager.shared.boxViewSizeNSRect + let styleMask: NSWindow.StyleMask = [.titled, .closable, .resizable, .miniaturizable] + let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) + windowInstance.title = "Box" + windowInstance.styleMask.insert(.resizable) + + let boxViewController = BoxViewController(nibName: nil, bundle: nil) + windowInstance.contentViewController = boxViewController + + windowInstance.setContentSize(BoxSizeManager.shared.boxViewSizeNSSize) + super.init(window: windowInstance) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func windowDidLoad() { super.windowDidLoad() - window?.styleMask.insert(.resizable) - - // BoxViewController 인스턴스를 생성합니다. - let boxViewController = BoxViewController() - - // BoxViewController의 뷰를 윈도우의 콘텐트 뷰로 설정합니다. - window?.contentViewController = boxViewController - - print("boxwindowcont") // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. } - } From f7909dc37cdb73e95d00e63a2c94409b11846eb2 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 14 Aug 2023 20:04:12 +0900 Subject: [PATCH 15/55] =?UTF-8?q?fix(Layout):=20autolayout=EC=97=90=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=EB=A5=BC=20=EC=9D=BC=EC=9C=BC=ED=82=A4?= =?UTF-8?q?=EB=8D=98=20setContentSize=EC=9D=84=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 6 +- Box42/Box/BoxButtonView.swift | 124 ------------------ .../Preferences/Accessibility.swift | 0 Box42/{ => Scripts}/Preferences/Hotkey.swift | 0 Box42/{ => Scripts}/Preferences/Icon.swift | 0 .../Preferences/PreferencesController.swift | 0 .../Preferences/PreferencesView.swift | 0 Box42/Window/BoxWindowController.swift | 2 - 8 files changed, 3 insertions(+), 129 deletions(-) delete mode 100644 Box42/Box/BoxButtonView.swift rename Box42/{ => Scripts}/Preferences/Accessibility.swift (100%) rename Box42/{ => Scripts}/Preferences/Hotkey.swift (100%) rename Box42/{ => Scripts}/Preferences/Icon.swift (100%) rename Box42/{ => Scripts}/Preferences/PreferencesController.swift (100%) rename Box42/{ => Scripts}/Preferences/PreferencesView.swift (100%) diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 8385287..ceff194 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -18,7 +18,7 @@ class BoxBaseContainerViewController: NSViewController { panGestureInit() viewInit() } - + func BoxButtonViewGroupInit() -> BoxButtonViewGroup { let buttonGroup = BoxButtonViewGroup { sender in // 버튼을 클릭할 때 실행할 코드 @@ -27,7 +27,7 @@ class BoxBaseContainerViewController: NSViewController { view.addSubview(buttonGroup) return buttonGroup } - + func clickBtn(sender: NSButton) { guard let clickCount = NSApp.currentEvent?.clickCount else { return } if sender.title == "Preferences" { @@ -51,7 +51,7 @@ class BoxBaseContainerViewController: NSViewController { WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() } } - + private func panGestureInit() { let panRecognizer = NSPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) self.view.addGestureRecognizer(panRecognizer) // 뷰 컨트롤러의 뷰에 제스처 추가 diff --git a/Box42/Box/BoxButtonView.swift b/Box42/Box/BoxButtonView.swift deleted file mode 100644 index fda1196..0000000 --- a/Box42/Box/BoxButtonView.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// BoxButtonView.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa - -class BoxButtonViewGroup: NSView { - // var boxButtonGroup = NSView?.self - var topAnchorDistance: CGFloat = 0 - - func createButton(_ title: String, clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - - button.title = title - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 30 - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createHomeButton(clickAction: @escaping (NSButton) -> Void) { - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: handler, action: #selector(handler.buttonClicked(_:))) - - button.translatesAutoresizingMaskIntoConstraints = false - button.isBordered = false - button.imagePosition = .imageOnly - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.topAnchor.constraint(equalTo: super.buttonBoxGroup.topAnchor, constant: topAnchorDistance).isActive = true - topAnchorDistance += 80 - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createQuitButton() { - let button = NSButton() - button.title = "Quit Box" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(NSApplication.terminate(_:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -10).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func createPinButton(clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - button.title = "Pin Box" - button.setButtonType(.toggle) - button.contentTintColor = .orange - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -50).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - - func preferencesButton(clickAction: @escaping (NSButton) -> Void) { - let button = NSButton() - button.title = "Preferences" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - - let handler = BoxButtonHandler() - handler.clickAction = clickAction - - button.target = handler - button.action = #selector(handler.buttonClicked(_:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.buttonBoxGroup.addSubview(button) - - button.leadingAnchor.constraint(equalTo: super.buttonBoxGroup.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: super.buttonBoxGroup.bottomAnchor, constant: -90).isActive = true - button.trailingAnchor.constraint(equalTo: super.buttonBoxGroup.trailingAnchor, constant: -20).isActive = true - } - -} diff --git a/Box42/Preferences/Accessibility.swift b/Box42/Scripts/Preferences/Accessibility.swift similarity index 100% rename from Box42/Preferences/Accessibility.swift rename to Box42/Scripts/Preferences/Accessibility.swift diff --git a/Box42/Preferences/Hotkey.swift b/Box42/Scripts/Preferences/Hotkey.swift similarity index 100% rename from Box42/Preferences/Hotkey.swift rename to Box42/Scripts/Preferences/Hotkey.swift diff --git a/Box42/Preferences/Icon.swift b/Box42/Scripts/Preferences/Icon.swift similarity index 100% rename from Box42/Preferences/Icon.swift rename to Box42/Scripts/Preferences/Icon.swift diff --git a/Box42/Preferences/PreferencesController.swift b/Box42/Scripts/Preferences/PreferencesController.swift similarity index 100% rename from Box42/Preferences/PreferencesController.swift rename to Box42/Scripts/Preferences/PreferencesController.swift diff --git a/Box42/Preferences/PreferencesView.swift b/Box42/Scripts/Preferences/PreferencesView.swift similarity index 100% rename from Box42/Preferences/PreferencesView.swift rename to Box42/Scripts/Preferences/PreferencesView.swift diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index affb589..db80f60 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -18,8 +18,6 @@ class BoxWindowController: NSWindowController { let boxViewController = BoxViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController - - windowInstance.setContentSize(BoxSizeManager.shared.boxViewSizeNSSize) super.init(window: windowInstance) } From 86b0b87cdf14491830dc65bd81a62d7c27f90cbe Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 14 Aug 2023 20:07:41 +0900 Subject: [PATCH 16/55] =?UTF-8?q?build:=20xcuserdata=EB=A5=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=ED=95=98=EA=B3=A0=20gitignore=EC=97=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 ------ .../xcschemes/xcschememanagement.plist | 14 -------------- 3 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist delete mode 100644 Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/.gitignore b/.gitignore index f24b421..f031450 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store Box42/.DS_Store +Box42.xcodeproj/xcuserdata/ .prettierrc .swift-format \ No newline at end of file diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index 955e565..0000000 --- a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist b/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2d4f387..0000000 --- a/Box42.xcodeproj/xcuserdata/chanheki.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - Box42.xcscheme_^#shared#^_ - - orderHint - 0 - - - - From 98268c444465f864b2ef5e9f9b10b98e971f88d3 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Tue, 15 Aug 2023 15:32:34 +0900 Subject: [PATCH 17/55] fix(xcode): listup --- Box42.xcodeproj/project.pbxproj | 104 ++++++------ .../UserInterfaceState.xcuserstate | Bin 187119 -> 199379 bytes Box42/Box/BoxButtonViewGroup.swift | 4 - Box42/Preferences/Accessibility.swift | 23 +++ Box42/Preferences/Hotkey.swift | 38 +++++ Box42/Preferences/Icon.swift | 19 +++ Box42/Preferences/PreferencesView.swift | 9 ++ .../PreferencesViewController.swift | 152 ++++++++++++++++++ 8 files changed, 299 insertions(+), 50 deletions(-) create mode 100644 Box42/Preferences/Accessibility.swift create mode 100644 Box42/Preferences/Hotkey.swift create mode 100644 Box42/Preferences/Icon.swift create mode 100644 Box42/Preferences/PreferencesView.swift create mode 100644 Box42/Preferences/PreferencesViewController.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 90cda27..c3b48a3 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -18,27 +18,30 @@ DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */; }; DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; - DE018BF92A509B3B00FF0AA3 /* BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */; }; - DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */; }; - DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BFE2A509B4200FF0AA3 /* BoxView.swift */; }; DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; + DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; + DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; + DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A132A8B506600A88DD8 /* keyMapping.sh */; }; + 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 */; }; + DE1F1A242A8B50D500A88DD8 /* BoxButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */; }; + DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */; }; + DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */; }; + DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */; }; DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; - DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesController.swift */; }; + DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7A25792A6D8CA20043225A /* PreferencesViewController.swift */; }; 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 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; - DE9BCA0D2A8360460031CA7B /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9BCA0C2A8360460031CA7B /* BoxViewModel.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 */; }; - DEB862EC2A853F7F00278FCD /* BoxWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */; }; DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; - DEF749372A8565C400D987C8 /* BoxButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749362A8565C400D987C8 /* BoxButtonView.swift */; }; - DEF7493B2A85683F00D987C8 /* BoxButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -55,29 +58,32 @@ DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarViewController.swift; sourceTree = ""; }; DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; - DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxViewController.swift; sourceTree = ""; }; - DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxModel.swift; sourceTree = ""; }; - DE018BFE2A509B4200FF0AA3 /* BoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; + 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 = ""; }; + DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxContentsViewGroup.swift; path = Box/BoxContentsViewGroup.swift; sourceTree = ""; }; + DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxButtonViewGroup.swift; path = Box/BoxButtonViewGroup.swift; sourceTree = ""; }; + DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxButtonHandler.swift; path = Main/BoxButtonHandler.swift; sourceTree = ""; }; + DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewModel.swift; path = Main/BoxViewModel.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 = ""; }; DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.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 /* PreferencesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesController.swift; sourceTree = ""; }; + DE7A25792A6D8CA20043225A /* PreferencesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; 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 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; - DE9BCA0C2A8360460031CA7B /* BoxViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxViewModel.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 = ""; }; - DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BoxWindowController.xib; 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 = ""; }; - DEF749362A8565C400D987C8 /* BoxButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxButtonView.swift; sourceTree = ""; }; - DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxButtonHandler.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -111,6 +117,8 @@ DE018BB12A5099F900FF0AA3 /* Box42 */ = { isa = PBXGroup; children = ( + DE1F1A202A8B50CA00A88DD8 /* Main */, + DE1F1A182A8B50BB00A88DD8 /* Box */, DEF749302A85655E00D987C8 /* Extensions */, DEB862E82A853F6800278FCD /* Window */, DEB862D22A8511D600278FCD /* Scripts */, @@ -119,9 +127,7 @@ DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* CPU */, DE018C082A509BB500FF0AA3 /* WebView */, - DE018C0B2A509BC100FF0AA3 /* URL */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, - DE018C102A509C1A00FF0AA3 /* Box */, ); path = Box42; sourceTree = ""; @@ -137,6 +143,7 @@ DE018C082A509BB500FF0AA3 /* WebView */ = { isa = PBXGroup; children = ( + DE018C0B2A509BC100FF0AA3 /* URL */, DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, ); @@ -176,28 +183,37 @@ path = Menubar; sourceTree = ""; }; - DE018C102A509C1A00FF0AA3 /* Box */ = { + DE17AF722A834A1600325BF4 /* Frameworks */ = { isa = PBXGroup; children = ( - DEF749352A8565B000D987C8 /* View */, - DE9BCA0C2A8360460031CA7B /* BoxViewModel.swift */, - DE018BF82A509B3B00FF0AA3 /* BoxViewController.swift */, - DE018BFB2A509B3E00FF0AA3 /* BoxModel.swift */, - DEF7493A2A85683F00D987C8 /* BoxButtonHandler.swift */, ); - path = Box; + name = Frameworks; sourceTree = ""; }; - DE17AF722A834A1600325BF4 /* Frameworks */ = { + DE1F1A182A8B50BB00A88DD8 /* Box */ = { isa = PBXGroup; children = ( + DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, + DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, + DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, ); - name = Frameworks; + name = Box; + sourceTree = ""; + }; + DE1F1A202A8B50CA00A88DD8 /* Main */ = { + isa = PBXGroup; + children = ( + DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */, + DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */, + DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */, + ); + name = Main; sourceTree = ""; }; DE77BA542A82636500713683 /* Shared */ = { isa = PBXGroup; children = ( + DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */, DE77BA552A82637900713683 /* StateManager.swift */, ); path = Shared; @@ -206,7 +222,7 @@ DE874F512A591EC600FC3B77 /* Preferences */ = { isa = PBXGroup; children = ( - DE7A25792A6D8CA20043225A /* PreferencesController.swift */, + DE7A25792A6D8CA20043225A /* PreferencesViewController.swift */, DE874F532A591F1400FC3B77 /* PreferencesView.swift */, DE874F562A591F2500FC3B77 /* Icon.swift */, DE2AD3282A824EEB00002D51 /* Accessibility.swift */, @@ -227,6 +243,9 @@ DEB862DE2A85348600278FCD /* sh */ = { isa = PBXGroup; children = ( + DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */, + DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */, + DE1F1A132A8B506600A88DD8 /* keyMapping.sh */, DEB862D32A85124500278FCD /* cleanCache.sh */, DEB862D82A852C4500278FCD /* brewInGoinfre.sh */, DEF7492E2A85603700D987C8 /* nodeInstall.sh */, @@ -238,7 +257,6 @@ isa = PBXGroup; children = ( DEB862E92A853F7F00278FCD /* BoxWindowController.swift */, - DEB862EA2A853F7F00278FCD /* BoxWindowController.xib */, ); path = Window; sourceTree = ""; @@ -252,15 +270,6 @@ path = Extensions; sourceTree = ""; }; - DEF749352A8565B000D987C8 /* View */ = { - isa = PBXGroup; - children = ( - DE018BFE2A509B4200FF0AA3 /* BoxView.swift */, - DEF749362A8565C400D987C8 /* BoxButtonView.swift */, - ); - path = View; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -318,9 +327,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */, DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */, + DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */, + DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */, DEB862D42A85124500278FCD /* cleanCache.sh in Resources */, - DEB862EC2A853F7F00278FCD /* BoxWindowController.xib in Resources */, DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */, DE018BE02A509B0600FF0AA3 /* Assets.xcassets in Resources */, ); @@ -333,30 +344,31 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DE018BFF2A509B4200FF0AA3 /* BoxView.swift in Sources */, + DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, - DE9BCA0D2A8360460031CA7B /* BoxViewModel.swift in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, + DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, - DEF749372A8565C400D987C8 /* BoxButtonView.swift in Sources */, - DEF7493B2A85683F00D987C8 /* BoxButtonHandler.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, - DE018BF92A509B3B00FF0AA3 /* BoxViewController.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, + DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, - DE7A257A2A6D8CA20043225A /* PreferencesController.swift in Sources */, + DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, + DE1F1A242A8B50D500A88DD8 /* BoxButtonHandler.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, + DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, - DE018BFC2A509B3E00FF0AA3 /* BoxModel.swift in Sources */, DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, + DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, + DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate index 6643712816c4033543191d1bfd4fcf964579c85c..96111f95f45e8662e2f55e9f09dd1611499d350d 100644 GIT binary patch literal 199379 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%0A)F_XzbyW&2=+*n>^MtL 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 &>#O|3E$;F! zk9fj!^z-+!LT%ng<~A9~L{{W(qkEfNAGQ>Br+-;4iLlotxa|883s7|F~zU{Tn185xFT&8Q#a; zw698a?4-SJ?R9DI-R)cPBkrhu7~RmPy*p|zSNjo6W--g~4YXg)I^=D?nctDSz1;23 zVD9ZNB6It{xrV!H@2=YG-u^xhg3wQ9@KX^!p$n7nyr1l=Lp*#39STs0qUhA2Jif0E zwW&u#KB5s#_?{nVO*`5%lnG2>8t$gUT;^jZ9dzrUONZSY;4to}!zuLXpic*VI`}3! zya+-aQ}PyR@eOp$Og7~0=>9wAMedFjsX{em?r8QM>r$T&kh`Pq9Y4eDJC0!$CwLx& zI(c5FnzUd5?x@o!#u9^@>7+-e1uSAIEBKYIZ08U5u%Cn2L8qs@3PNG-Cd}Q0B_avQ z(Jf4uupAVkIHmBthUpVl8GXX^36njnDV^~hghkMcKJ;f0(F|iG<{ma1nZwLJY$0YJ zCU=`@TvoDn>tHwG4QWgp^ak_`4m8@nh8`#7ae&+(_-{oD*u}f<_uZtOUaeH0#>S9M-+*+5{L8z-jXxSNQ&G~h$zjrfc&kvrliI?)-KBg{U+>?6!Rq7QOM=pGS; z*+;mKh^s-UM#2*sl@;pQgch`-EgjIOXE<{8^iA{}%N*QI&tF)=a^&r~hV{tZ zQ*M7BE7bEiCy}|Q+4sD_U&!3kUG==dtsvAZG5IjtUgp@#dwQ+K&-BtKG7~w;gKs*r zAi6|WM2E=g*iWSWMAoMvpJO+XKcG)!dwds>b`xngkv*`R$YG2m4t*l^iPR@jpGbWo z^@-Fc(jFprvKzS~b&0%$9YpFAc^!Qs-B#pX>?HDG5bB+pqI`-u_MVLA_5M2u^?3u| zM<0Fq6s8!yg+3LiNged*^8p|82~BBEOWN=wKcPpTiA-fWGnvN%7NJ`oUHW);pZy%+ z81~cW9QyRJn?C=~^&klK4M;;eGLnVt$lEtJ_SIMJzH;}iN)7CwugrbxVF!KPR^LYG z-uDZ>!VLPl@xJRg!|Nc_&-41(UBA{0#<$&X9I@!s?`IaWm}RVFHEY?y9(3w=2%Y+! z;57Es?aSOSz546bzZ3HI z|CQrB3qk`tZ-99Wu%`k2v6}%S8G~K}rZ9*3{K68Jqt^iY8L$nvHefgVIDj4lp71gV z`9EI@4U9)Zl8_AD2I?}f07WQHDaxVGKz#=4Gw>t6r6ZlOkAV^Nq7U*897Hs75A-{A zp!pA+h0Fup)WC(<#lU5(U=_ZXfk$}|ga(=Ip!e~fK?CqJgY+46g*)8mA&;^Ds6-@1 zhp5!NO*%4QM^QN`iat?gDNhxuQIpzyj{Aygi9S*KMClWyPn14U`b6myH4=M>ib1X@ zU7~y+QA^M#$_}FRiE>*}>)FI+&f|jV{WFC?OyBLxivmeq7vmIiNL%he| zve{zA9{!*9OE=+ zxqxm%bs4J5&__XNSUk*rSQ3)+7H{J&hh-!mrKm%FKHy_MM`R&8?_v)lbQw_)w=|+EHK>JdBkIwR4{3ycBlH{b6*`R=&pOWV zItY#Qypetnk8F)zBS&K=Bkg3QTN`N?BNwumWvpa1zLk+X*o8ffJiuZ8M30d#gU~2D z85JLU8RgDKxwBF3Y?N-JbQx6yvl>-~a#Tj2QTmM1XVhnWPb=EumPUoqh3@n~=23Pr zY8ZAgY9FW2Z`3(12BFcpC`J{k~jrOk59qEj@jgG)A zjJE61oKKY-}F#W4B{J zpbZ0A!G5j>p>gIn&UZP^J&f~nGtj6xg?dDI8V;;`4 z++*Bkj65+P@d;)g)0pN&<9#u1EyjCdyeDQI8*pPW$2f_-#+=8TWB%qE5BZO0ybMC) z1KuD3i6}%}I-=Wn&mJ%D_$!#{_?z6pGh#!$Nj}UoR_<82W95yNH8z4?^r1h4h{pZJ zy1&>l#4v%$Ol1bMn9EY^GuGT<%`5gVUIn2E2}y!?PB6C#<~G4x{OzaEgbs{j3e(xh z4t8-5H|B3bg(jva2RW&QolkVz6Mv!`J=n?~+|wlg?4#}_okJ16yHC<|H6Va$1w zIZt}TW1a+|$?-`=8q$%GEM%tu=03S7B`D4Nl&2k&kbkmg#pR|lzQ?$4aHDa}XhAF5 z(jNQsH?F0Dp`-v!`h$0FiAP9&E2nvFL zWo2dMXj6mY$t-uFG%^*Q}>c<%fD z-uLsnuJgxv&g55E$U2&W(3E6KvA-$z@Hl3h;_s$BjU7#y%oL_E2XjxU<8|~n#qCXL zWIf-q33*J}%-`(B98+4^AB3iMrYqfvCxP?0oPTpCdYNjLsb-m~r>RfzEH7Y=sqZ28 zso(J0F2#s#2p$jVe2? zGFO$|R?X)%en*Z~a;$2mB?wK=L+{foID(_NjfZe^(`7dO2|ng)^fG-74Xnp~O!urA z_Ax_7GddDY46)==Oey8aXoh}gT#or?n19AC+{zu?jrnJ|&l&bH!#-xb&0^~LoUf3@ z4EHhPFWkorw>VS%nVpc&%v98zc_d@G9?zaRfd`QFOtZ~=oELbRiM)!eX1Y)76m_pq0iAXMFhG&1N<4l=0DryLnq%eZnJ&63xw4s;}% z7?Ma~AVcvU&2k&F*9v5;ka-MY~`k$ru+35_TkRf>H>>v4?t;le; z4Ck0-PAzrFe~ww^y5qSw<2iG^A9L>tLN#)%DMwE=ZmC9JHKX|#C!@ET^SJ;$)##~4 zPc<^F(N~SWYVPBH9>AT~JjaW?!X&1kpPKpTqvm7Q;ofV$L;p3uu#ru;!5XvFG_flP z&6DXocQ~&LUFn9qnAeNmB-0n!%yTF6%rsA~^YrfjYbZ4D9`rMBE{kbkJ8rx-AQJnj z9gIwCWl`&nYW;of8Q4p$z0_XBrO2_?b8D}~T(t{X!}sXFR{yp7uhoC8{%f0Q2}1MT z$NbKiVSabw=|d`dpPz{vpRexx3C!ayK41weklTE@&6nGJxy}EbKe7M$+fZ}M=uoA~LDhW4)c!59LUX z!}II)RBs>k_E0~b>$wTJ)w{!bcUb=jkMkri@n0t49_wc@n;PC^IbZM%4h ze~mA3JD+b0LMuN-?knB!%0Jl57Pe!?m3!Dn8wZ2Xs(?7$@2UinNI{KNZfjM429QfW z=2|72Rq|MMH_u`RtK_~)-BmJKCD&ClUA2p5^t@_6hl0@R5D}=kx+iX9wfAPV_hz*l zS)EBXZe{fmcz;&Auhq}+1}ibknr`TGjo#MiZOtGCQ%otxa2zKft2L)^I(lDYCu^pn z-!<}C8_hsY#9V7{MZLAp^Ac`t?W_2kwN=byHZ{!WHO#-(p4NWDYS!T{)_%(m{DfTA zZp2>J{!`ap*4o+H13_qA56r#pXwK&j)L!=%cDk++|M_)?gHVIa8f4Ybk1U2@=7w@) z=DXCP2D3Mqz2PLT#7qqj@+4+!Fk6G?H<+!#ObupgFjIq>8qCzNfaPq$9veFlg}Z1} zv(b$=dVb>>=(kaBjW=@}@@>3}d$5Ii^}gO-*4xW^Gpsj*Z%>ET+sAtQSpN?1^8t3UUheA;1)&Y{+hB$b zZhM2wH@LM8$KpOVjA1NlZMXpSHr&m_OsASTL1@c`n0bpFw@kzwTRn5DUHCp^XzNjo zu-TRnHHytexLt(R~aS8xYr*}4dMY~93e_R@+xwjK^b+d{?19>rYS%(3lz)ZN}5b++eGN;ziRZno`a z+ite)GTSb*?PlA44rbdfv+e3`S7&<_>u3%_O}+5ECU@H;tEK@A0ZkxRCO)_ed zebdFrr|C+rLH|v1YVzEsd(eNA{+k}g-kaXx0~WJ{&+tArt>-&_@+QiU7aF`K!lw?myB%lLw?S;-FUY-a+=*v(G6**O}&Lpx=* z(~LW>;##ifCMNIz=Gkcul_Q z*S$Q#WTr8lYV3H|JnDFzw|JL@e8_J>Xm=ud-0d!Q`_Js&9)$K}V<&rF#=LvXx#tId z#^3DG+nzu9D+o1rz`NV*In8}YC4($Hr&;FBM{^nGZhnHNd5#x(g-J}Ik{QfG=FNUX znisH~FImAV*3!tg=&M;@&H8HASMz56W@`}I8z4L1OAPJ36dCQUVG+NwBM9y5ND6kg z?<~e~9v5;6`rhXb_u17xf4}c>p5j^bywBeD&Bk;0+21}H@00Pq_fcoxV!mPnTWID` z5Ne60JMkotL^_%DM{X^-9KrGEspV?Mb0^-5mb7SRUWN&*lLHZ@@Tcg zRz0-3rB+$A%A$24%lLw?aZjxc$e~T$HnX;wv&~(%$-B*bZEmDZ#%<5@5^A)0cAICl zE#W)tudNl&*&iZ;4!Fnt$@HZkSqxw>#gtNxn)}VR|4gpoHtc!-Gq}zDYVM!JG^SIH zZ1*qX8~oPn-$gSm>_;yL^m0Hi2lR5F6J3ZUj-DhU=K~eU^uRr+dBDC7nC*a!4*bnF z%y>YJ18N*l<%X2SqD={BLllTIFw`cNGar12 zN3hF-Phs|hRoLS}^B%0>T^8~oA5+g7)**+3-{KwgeZ-J&BZdx{^^nXDjpH(|<6+b| zqr*Q@saVb}DHRHLS zCz;4ps+hqX<}sfIEappAvW5n};|G4`S9S#9u%5#`=tUxZNJX#VOtKly2#(=6PGB@+ zxPXhfj4QbYeTMJk9`55o^ck+>b>8A#KH@9BVKwW}S6E)*Klz(|v~iHbLAc%dsL@W1 zcCu)96Vvg$cIz=?yC3<5jcnpCw$c=YBO>TPC%O?k6iLhLBQ>=9;< zFnfgABg`CeE$T<8A8`v4u$PEuc%GNgS41^-6ETnX_<+THjGiJ|gK+zRc0>||p4xXO zo&DkTx1_9`^f9Kk(+rL_ZK;fxzwVE$fYdjOIBbnk@ga4FOl{VX(y3; zX<ITd|&IFqv($9c%A!^K?6{Z#T9e+1!1d9Q^6Y4qjvug?C49!<{h zFk6&aqK0t!d&5gba5|BcDRtMW+(<*y(sqReHmBc#-i_L0uS&okMaahF^MVI zZM2<5zs_RpDcY{1m+=)FFnjb*{EFFq4>BCRhkZe~a|9jGZ|5%b#;!W|B^`I(`F}pI_snJ@BGPMY(-yP?4wH#Cu9CD z>U8-4f79h)5RU0XCfUd~CXb;U$a+*HgZT+UTogE?Y6KSqu*lbOa$ zW-%AD#h4|=3^8s#W*zG>N6gQdA;t_bn`lOVT~kOS1MhFw0pv1>!4z{Mdh2>B-odVC zF%JE8y_V~_iCegxJMkWLeH?r5`Yd|wTFV07;B7u(Da-j1y>``W*B|+XZR}t-`i+%W ztbAfmLm#pFh#k+ntbAhY`JC0L8LOsmEQVt@BA?jJ z{8O`q{TvFy-MY}5WZYV}e&kcm5gf%x^w;f7&gLAh#QwTn#|^mkZmaN{)Xk2%nY&w4 z5bhpJ96d?I?Q~BiolLSB&Ipd-I8IaO?UOW-^2tS;9=a6?=FVB&tx_= z%;z;^)Llm1Wz=0p-B%!=?(*p_pY9v6lkRrXeJ`y+I4+VXIupYss2itl+|As^Q%pjg zICbLu2FAU^`z+!k+=Fj5hU45roSJcJ#<|C2~ZdVZQ(G`2>aXN0W zhyC~PydJ*=;rI}C6+eJn22n^E$8a1cFq%`ayZ8&Zn9H!cc)N=q&*R7~-fhKCr3&v} z{2bP!dyV5<hw~lm%a9qMX!%gtCw26)aoUhUY?l{hg~GtL4sKl zuI5H=#=RumiT-{6F`V!p9^(nzP=cHj0*X*DzP2TT7HzqWX#EOWYlV zdk3i7J4^)KNFj|3`lFZLc@!|5BRQIp9M6f2=48fU*S+=CTkYN-B7@$)vkkR-|5LX) z2q&qX)P)$jqIS|?%$j7@B(o-|mox%9NIDMhL6Z5CF6J`ikaP{#VJAuVVIN8Mkz^l9 z@<@6bH@3LZ%KaNlJuDLCx4^Yq&5x){_6|vh$W7m*i)aocogqkA9ec3 zz0V9jL*9M9;49SWqfQ@n`l!?AJM5v48|Wj4J}vC$P!LY;fI7+QB&(C0NFVGZc_8@| zQiM#BPvs2GLiWk$BadWxB;Ux*+|NTif?ktfVG>iA#uoIDY~EzInCuo)24Tl3Cvh^T zaVDOhatHRCGJ#6WoHC2K)Utp#c#C)W3K^uxAVmf#GDwj@%0|4yDY8hBMT#s^^x->{ z;Z!-KcA^XNNKK|M{m5bnLm5T|?jqF<`UYh<^>oJK4pXm09;xHGlc#u=7kHV8Ohyi= z)2U_-AF!B@aVx2xVW+8n8&b`ax`I`#LH~VY7>tbi%BQdA_5GAzgK(PrNsFR0UFk+| z%#vo7v;pKYh(eCwC`NKTCo-C=xeeK;-HW}Zx%0F~c>=SgnI+90(&~5}J4kyU^Q4(4 z%{*y#k!A;J`cB&ugwyqvp29$iD4~quj6k;O>ZhNAY}3bZHr~JVYq_4AxCOnXPv8L_ z#?7VcDSZJ;_=2C1OZxBp$=_^a2fNuzD{e9UP!R5yN;;YJCx<)=a0mU|LBEqYnbWX? ze){Wo4wo{X8~8W3Vn6-vLT>%!*6(SaqlR}`$cMOLpB+*$&gKk zY%PQkPq>+JrWZ6fSePr23mVIQ|N0yt(Qa8&^vQFi6#$Yd5_L8NSEWKo1%mk+L z2^)iO{|i&ia3ZJL|uKRjj3vZ}}dxWVfdi zo#~3)vU`$<`LfNET|xy%ax}+drff51n<@Kz>^ECp+0XDiFY*eLm_jA?o~^%Z`_1+HR>av%r~=#8ug=xu;(2FQAV_jAAqj^Q}Y z;4H>*9#=CSyB=^8vKa6SzoE{6KiMCIbNY})a)LMm^@qHBasazQ?|Ef8k&d&g(>1 zy5kn}60wuK6wH=qmb?m%VkB-cZ#3q~Gf$p*@-E>9ZsB(B=TV-bj@Nk$dFRPHPu_X* z&ifSo<$cGG=qYa_oA`@e$U9Ho`5_|cKomXEYrbCd-A}&U^Y!XmnqlA44Cf!sv5ev* z#&RwfAZy>%4ClMcd_CvihRpL{VG>iQ#18Uhn?ILYWSsv7OIgkre8md9@A+$KM9%qg z&NowjTM!R zvXBpvapBjjL~n&Z^BaG#nPysWCxz~L@af2TupJM+lq+|2SJaM3qOj|t9wgJ3 zeq=F#fs|5?9Ty$NNRGoCMK>b1qC2>Y`*;u;7MZQcEJg0sw>85>^QhxZ%u{5ZBJ&j4 zbCI5lw$j8-_OOqCdX-<%;UHYB$Kqb}Mz6(sE!JzXIel|8T&&MxeHQDpSf9nma4KhT z7UQ^rs~L~I7vF=Pi}hUmALL)G=VEykPi8K)EZ}v%W*a-$O*1X*=THzH8X|&3`jARG znPgK)8N(TY9*4?u=qSc8mUFoPy$yYwr*IoX^)|E;c@CY0-h7)g?Ax5-p^Ny4ulR=5 ztPR2?>Xpc&M6HseITjg|$e=_9B{C>+A0@YP2X`}p7kPzAOhMfebxUMXVs|BWSMmXi zS;D8RWDN~$U?XxWkyFWDT7z(DBvEvxD>5pTQE56dDjiHQrO2t&{H6LRoye<9#jK^D zqh6_crRtTcSNb!*@;iU>R}dc73BL!!ya&U~Jj|@a?&CrJ!(%+jGd#~rs4;9B({Z!I z-0U#BANCd>@-gNeR?ly2!JNa)In12H%vsir-nh@QEC!IvAk0`cmW#QHYq_4AxCOP# zyf0;Hm#JN*cG*JIE>pYg7t}2?XW1q;qlYqgS=Pi(4h7-z4w%2Z3$er@@A6dAk#~7E zISj!~mXG2huH!cDwOw%~vN6%qcwe-0V{fB*dde-96D_dg3(?Q{SD literal 187119 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²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

xRh1ZpM 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 bXCC*2{`XHL{KcOKw14sE|NkBC{^NfEMg5Gb diff --git a/Box42/Box/BoxButtonViewGroup.swift b/Box42/Box/BoxButtonViewGroup.swift index 4b51f0d..e71a3f8 100644 --- a/Box42/Box/BoxButtonViewGroup.swift +++ b/Box42/Box/BoxButtonViewGroup.swift @@ -31,10 +31,6 @@ class BoxButtonViewGroup: NSView { // 뷰의 커스텀 렌더링에 사용됨. } - override func layout() { - // layout(): 뷰의 서브뷰들이 리사이징될 때 호출됩니다. 레이아웃을 조정하는 데 사용됩니다. - } - private func setupButtons() { createHomeButton() for (name, _) in boxVM.webViewURL.URLstring { diff --git a/Box42/Preferences/Accessibility.swift b/Box42/Preferences/Accessibility.swift new file mode 100644 index 0000000..7121713 --- /dev/null +++ b/Box42/Preferences/Accessibility.swift @@ -0,0 +1,23 @@ +// +// Accessibility.swift +// Box42 +// +// Created by Chanhee Kim on 8/8/23. +// + +import Cocoa + +func alertAccessibility() { + let alert = NSAlert() + alert.messageText = "Permission Required" + alert.informativeText = "Please allow accessibility permissions in System Preferences to enable this feature." + alert.addButton(withTitle: "Open System Preferences") + alert.addButton(withTitle: "Cancel") + let response = alert.runModal() + + if response == .alertFirstButtonReturn { + if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") { + NSWorkspace.shared.open(url) + } + } +} diff --git a/Box42/Preferences/Hotkey.swift b/Box42/Preferences/Hotkey.swift new file mode 100644 index 0000000..64a71f1 --- /dev/null +++ b/Box42/Preferences/Hotkey.swift @@ -0,0 +1,38 @@ +// +// Hotkey.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +import Foundation + +import Cocoa + +func hotkey() { + let eventMask: CGEventMask = (1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue) + guard let eventTap = CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: eventMask, callback: { (proxy, type, event, refcon) -> Unmanaged? in + if [.keyDown, .keyUp].contains(type) { + let flags = event.flags + let isCommandPressed = flags.contains(.maskCommand) + let isControlPressed = flags.contains(.maskControl) + let keyCode = event.getIntegerValueField(.keyboardEventKeycode) + + // keyCode 11 corresponds to the 'b' key + if isCommandPressed, isControlPressed, keyCode == 11 { + print("Command + Control + B pressed!") + } + } + + return Unmanaged.passRetained(event) + }, userInfo: nil) else { + print("Failed to create event tap") + return + } + + let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) + CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes) + CGEvent.tapEnable(tap: eventTap, enable: true) + + CFRunLoopRun() +} diff --git a/Box42/Preferences/Icon.swift b/Box42/Preferences/Icon.swift new file mode 100644 index 0000000..d256436 --- /dev/null +++ b/Box42/Preferences/Icon.swift @@ -0,0 +1,19 @@ +// +// Icon.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +struct iconModel { + var icon: [String] = [ + "Cat", + "gam", + "gon", + "gun", + "lee", + "Box", + "box_oc", + "42" + ] +} diff --git a/Box42/Preferences/PreferencesView.swift b/Box42/Preferences/PreferencesView.swift new file mode 100644 index 0000000..d2abcff --- /dev/null +++ b/Box42/Preferences/PreferencesView.swift @@ -0,0 +1,9 @@ +// +// PreferencesView.swift +// Box42 +// +// Created by Chanhee Kim on 7/8/23. +// + +import Foundation + diff --git a/Box42/Preferences/PreferencesViewController.swift b/Box42/Preferences/PreferencesViewController.swift new file mode 100644 index 0000000..786e21d --- /dev/null +++ b/Box42/Preferences/PreferencesViewController.swift @@ -0,0 +1,152 @@ +// +// PreferencesViewController.swift +// Box42 +// +// Created by Chanhee Kim on 7/24/23. +// + +import Cocoa +import Foundation + +class PreferencesViewController: NSViewController { + let menubarVC = MenubarViewController() + private var stackView: NSStackView! + private var rightView: NSView! + private var outputView: NSTextView! + + override func loadView() { + self.view = NSView() + self.stackView = NSStackView() + self.stackView.orientation = .vertical + self.stackView.distribution = .fillEqually + self.stackView.spacing = 20 + self.view.addSubview(stackView) + stackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + stackView.topAnchor.constraint(equalTo: self.view.topAnchor), + stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), + stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) + ]) + + let leftView = NSView() + self.rightView = NSView() + self.stackView.addArrangedSubview(leftView) + self.stackView.addArrangedSubview(rightView) + + outputView = NSTextView() + outputView.translatesAutoresizingMaskIntoConstraints = false + rightView.addSubview(outputView) + + NSLayoutConstraint.activate([ + outputView.topAnchor.constraint(equalTo: rightView.topAnchor), + outputView.leadingAnchor.constraint(equalTo: rightView.leadingAnchor), + outputView.trailingAnchor.constraint(equalTo: rightView.trailingAnchor), + outputView.bottomAnchor.constraint(equalTo: rightView.bottomAnchor) + ]) + + + var stackBox: [NSView] = [] + + let icons = iconModel().icon + icons.forEach { (icon) in + stackBox.append(NSButton(title: "Change \(icon) Icon", target: self, action: #selector(changeIconButtonPressed))) + } + + let scripts = Scripts().info + scripts.forEach { (script) in + stackBox.append(NSButton(title: "\(script.name) Script: \(script.description)", target: self, action: #selector(scriptButtonPressed))) + + } + +// let scriptButton = NSButton(title: "Script", target: self, action: #selector(scriptButtonPressed)) + let appleScriptButton = NSButton(title: "Apple Script", target: self, action: #selector(scriptButtonPressed)) + let etcButton = NSButton(title: "Etc.", target: self, action: #selector(etcButtonPressed)) + +// stackBox.append(scriptButton) + stackBox.append(appleScriptButton) + stackBox.append(etcButton) + let buttonStackView = NSStackView(views: stackBox) + buttonStackView.orientation = .vertical + buttonStackView.distribution = .fillEqually + buttonStackView.spacing = 20 + leftView.addSubview(buttonStackView) + buttonStackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + buttonStackView.topAnchor.constraint(equalTo: leftView.topAnchor), + buttonStackView.leadingAnchor.constraint(equalTo: leftView.leadingAnchor), + buttonStackView.trailingAnchor.constraint(equalTo: leftView.trailingAnchor), + buttonStackView.bottomAnchor.constraint(equalTo: leftView.bottomAnchor) + ]) + } + + @objc func changeIconButtonPressed(_ sender: NSButton) { + // Change the content of the right view for icon changing + let icon = sender.title.split(separator: " ").map{String($0)} + print(icon[1]) + menubarVC.menubarStopRunning() + menubarVC.buttonImageChange(icon[1]) + menubarVC.menubarStartRunning() + } + + @objc func scriptButtonPressed(_ sender: NSButton) { + let script = sender.title.split(separator: " ").map{String($0)} + if script[1] == "Script:" { + if let scriptPath = Bundle.main.path(forResource: script[0], ofType: "sh") { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = [scriptPath] + + let outputPipe = Pipe() + task.standardOutput = outputPipe + task.standardError = outputPipe + + + task.standardError = outputPipe + + outputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in + if #available(OSX 10.15.4, *) { + if let data = try? fileHandle.readToEnd(), let output = String(data: data, encoding: .utf8) { + DispatchQueue.main.async { + if let outputView = self?.outputView { + outputView.string += "\(output)" + } else { + print("outputView is nil") + } + } + } + } else { + // Fallback on earlier versions + } + } + + + task.launch() + task.waitUntilExit() + +// let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() +// let output = String(data: outputData, encoding: .utf8) ?? "" +// print("Output: \(output)") + } else { + print("Script not found") + } + } else if sender.title == "Apple Script" { + let appleScriptCode = "display dialog \"Hello, World!\"" + + if let appleScript = NSAppleScript(source: appleScriptCode) { + var errorDict: NSDictionary? = nil + appleScript.executeAndReturnError(&errorDict) + + if let error = errorDict { + print("Error: \(error)") + } + } + + } + } + + @objc func etcButtonPressed() { + // Change the content of the right view for etc. + } +} + From 1c6b847f23fcffe27b4458285293de8c03b7d87e Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:20:50 +0900 Subject: [PATCH 18/55] =?UTF-8?q?feat(tuist):=20tuist=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(tuist): Project 추가 * fix(tuist): Main.storyboard를 리소스에 추가하였습니다. --- Project.swift | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Project.swift diff --git a/Project.swift b/Project.swift new file mode 100644 index 0000000..7ab74f9 --- /dev/null +++ b/Project.swift @@ -0,0 +1,33 @@ +import ProjectDescription + +// MARK: Constants +let projectName = "Box42" +let organizationName = "Box42" +let bundleID = "com.box42" +let targetVersion = "10.15" + +// MARK: Struct +let project = Project( + name: projectName, + organizationName: organizationName, + packages: [], + settings: nil, + targets: [ + Target(name: projectName, + platform: .macOS, + product: .app, // unitTests, .appExtension, .framework, dynamicLibrary, staticFramework + bundleId: bundleID, + deploymentTarget: .macOS(targetVersion: targetVersion), + infoPlist: .file(path: "\(projectName)/Resources/Info.plist"), + sources: ["\(projectName)/**"], + resources: ["\(projectName)/Resources/Assets.xcassets", + "\(projectName)/Resources/Main.storyboard",], + entitlements: "\(projectName)/Resources/Box42.entitlements", + dependencies: [] // tuist generate할 경우 pod install이 자동으로 실행 + ) + ], + schemes: [], + fileHeaderTemplate: nil, + additionalFiles: [], + resourceSynthesizers: [] +) From 0c5bb3bbc3ab9ee489a05fdd28cbed5bb88f82de Mon Sep 17 00:00:00 2001 From: chanhihi Date: Tue, 15 Aug 2023 17:22:44 +0900 Subject: [PATCH 19/55] =?UTF-8?q?chore:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=EB=93=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Scripts/Preferences/Accessibility.swift | 23 --- Box42/Scripts/Preferences/Hotkey.swift | 38 ----- Box42/Scripts/Preferences/Icon.swift | 19 --- .../Preferences/PreferencesController.swift | 152 ------------------ .../Scripts/Preferences/PreferencesView.swift | 9 -- 5 files changed, 241 deletions(-) delete mode 100644 Box42/Scripts/Preferences/Accessibility.swift delete mode 100644 Box42/Scripts/Preferences/Hotkey.swift delete mode 100644 Box42/Scripts/Preferences/Icon.swift delete mode 100644 Box42/Scripts/Preferences/PreferencesController.swift delete mode 100644 Box42/Scripts/Preferences/PreferencesView.swift diff --git a/Box42/Scripts/Preferences/Accessibility.swift b/Box42/Scripts/Preferences/Accessibility.swift deleted file mode 100644 index 7121713..0000000 --- a/Box42/Scripts/Preferences/Accessibility.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// Accessibility.swift -// Box42 -// -// Created by Chanhee Kim on 8/8/23. -// - -import Cocoa - -func alertAccessibility() { - let alert = NSAlert() - alert.messageText = "Permission Required" - alert.informativeText = "Please allow accessibility permissions in System Preferences to enable this feature." - alert.addButton(withTitle: "Open System Preferences") - alert.addButton(withTitle: "Cancel") - let response = alert.runModal() - - if response == .alertFirstButtonReturn { - if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") { - NSWorkspace.shared.open(url) - } - } -} diff --git a/Box42/Scripts/Preferences/Hotkey.swift b/Box42/Scripts/Preferences/Hotkey.swift deleted file mode 100644 index 64a71f1..0000000 --- a/Box42/Scripts/Preferences/Hotkey.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// Hotkey.swift -// Box42 -// -// Created by Chanhee Kim on 7/8/23. -// - -import Foundation - -import Cocoa - -func hotkey() { - let eventMask: CGEventMask = (1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue) - guard let eventTap = CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: eventMask, callback: { (proxy, type, event, refcon) -> Unmanaged? in - if [.keyDown, .keyUp].contains(type) { - let flags = event.flags - let isCommandPressed = flags.contains(.maskCommand) - let isControlPressed = flags.contains(.maskControl) - let keyCode = event.getIntegerValueField(.keyboardEventKeycode) - - // keyCode 11 corresponds to the 'b' key - if isCommandPressed, isControlPressed, keyCode == 11 { - print("Command + Control + B pressed!") - } - } - - return Unmanaged.passRetained(event) - }, userInfo: nil) else { - print("Failed to create event tap") - return - } - - let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) - CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes) - CGEvent.tapEnable(tap: eventTap, enable: true) - - CFRunLoopRun() -} diff --git a/Box42/Scripts/Preferences/Icon.swift b/Box42/Scripts/Preferences/Icon.swift deleted file mode 100644 index d256436..0000000 --- a/Box42/Scripts/Preferences/Icon.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// Icon.swift -// Box42 -// -// Created by Chanhee Kim on 7/8/23. -// - -struct iconModel { - var icon: [String] = [ - "Cat", - "gam", - "gon", - "gun", - "lee", - "Box", - "box_oc", - "42" - ] -} diff --git a/Box42/Scripts/Preferences/PreferencesController.swift b/Box42/Scripts/Preferences/PreferencesController.swift deleted file mode 100644 index 1b9139b..0000000 --- a/Box42/Scripts/Preferences/PreferencesController.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// PreferencesView.swift -// Box42 -// -// Created by Chanhee Kim on 7/24/23. -// - -import Cocoa -import Foundation - -class PreferencesViewController: NSViewController { - let menubarVC = MenubarViewController() - private var stackView: NSStackView! - private var rightView: NSView! - private var outputView: NSTextView! - - override func loadView() { - self.view = NSView() - self.stackView = NSStackView() - self.stackView.orientation = .vertical - self.stackView.distribution = .fillEqually - self.stackView.spacing = 20 - self.view.addSubview(stackView) - stackView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: self.view.topAnchor), - stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - - let leftView = NSView() - self.rightView = NSView() - self.stackView.addArrangedSubview(leftView) - self.stackView.addArrangedSubview(rightView) - - outputView = NSTextView() - outputView.translatesAutoresizingMaskIntoConstraints = false - rightView.addSubview(outputView) - - NSLayoutConstraint.activate([ - outputView.topAnchor.constraint(equalTo: rightView.topAnchor), - outputView.leadingAnchor.constraint(equalTo: rightView.leadingAnchor), - outputView.trailingAnchor.constraint(equalTo: rightView.trailingAnchor), - outputView.bottomAnchor.constraint(equalTo: rightView.bottomAnchor) - ]) - - - var stackBox: [NSView] = [] - - let icons = iconModel().icon - icons.forEach { (icon) in - stackBox.append(NSButton(title: "Change \(icon) Icon", target: self, action: #selector(changeIconButtonPressed))) - } - - let scripts = Scripts().info - scripts.forEach { (script) in - stackBox.append(NSButton(title: "\(script.name) Script: \(script.description)", target: self, action: #selector(scriptButtonPressed))) - - } - -// let scriptButton = NSButton(title: "Script", target: self, action: #selector(scriptButtonPressed)) - let appleScriptButton = NSButton(title: "Apple Script", target: self, action: #selector(scriptButtonPressed)) - let etcButton = NSButton(title: "Etc.", target: self, action: #selector(etcButtonPressed)) - -// stackBox.append(scriptButton) - stackBox.append(appleScriptButton) - stackBox.append(etcButton) - let buttonStackView = NSStackView(views: stackBox) - buttonStackView.orientation = .vertical - buttonStackView.distribution = .fillEqually - buttonStackView.spacing = 20 - leftView.addSubview(buttonStackView) - buttonStackView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - buttonStackView.topAnchor.constraint(equalTo: leftView.topAnchor), - buttonStackView.leadingAnchor.constraint(equalTo: leftView.leadingAnchor), - buttonStackView.trailingAnchor.constraint(equalTo: leftView.trailingAnchor), - buttonStackView.bottomAnchor.constraint(equalTo: leftView.bottomAnchor) - ]) - } - - @objc func changeIconButtonPressed(_ sender: NSButton) { - // Change the content of the right view for icon changing - let icon = sender.title.split(separator: " ").map{String($0)} - print(icon[1]) - menubarVC.menubarStopRunning() - menubarVC.buttonImageChange(icon[1]) - menubarVC.menubarStartRunning() - } - - @objc func scriptButtonPressed(_ sender: NSButton) { - let script = sender.title.split(separator: " ").map{String($0)} - if script[1] == "Script:" { - if let scriptPath = Bundle.main.path(forResource: script[0], ofType: "sh") { - let task = Process() - task.launchPath = "/bin/sh" - task.arguments = [scriptPath] - - let outputPipe = Pipe() - task.standardOutput = outputPipe - task.standardError = outputPipe - - - task.standardError = outputPipe - - outputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in - if #available(OSX 10.15.4, *) { - if let data = try? fileHandle.readToEnd(), let output = String(data: data, encoding: .utf8) { - DispatchQueue.main.async { - if let outputView = self?.outputView { - outputView.string += "\(output)" - } else { - print("outputView is nil") - } - } - } - } else { - // Fallback on earlier versions - } - } - - - task.launch() - task.waitUntilExit() - -// let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() -// let output = String(data: outputData, encoding: .utf8) ?? "" -// print("Output: \(output)") - } else { - print("Script not found") - } - } else if sender.title == "Apple Script" { - let appleScriptCode = "display dialog \"Hello, World!\"" - - if let appleScript = NSAppleScript(source: appleScriptCode) { - var errorDict: NSDictionary? = nil - appleScript.executeAndReturnError(&errorDict) - - if let error = errorDict { - print("Error: \(error)") - } - } - - } - } - - @objc func etcButtonPressed() { - // Change the content of the right view for etc. - } -} - diff --git a/Box42/Scripts/Preferences/PreferencesView.swift b/Box42/Scripts/Preferences/PreferencesView.swift deleted file mode 100644 index d2abcff..0000000 --- a/Box42/Scripts/Preferences/PreferencesView.swift +++ /dev/null @@ -1,9 +0,0 @@ -// -// PreferencesView.swift -// Box42 -// -// Created by Chanhee Kim on 7/8/23. -// - -import Foundation - From 26efd86a8c6fc93fb0a90f39f3de46b9591b12cd Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Tue, 15 Aug 2023 23:11:42 +0900 Subject: [PATCH 20/55] =?UTF-8?q?feat(tuist):=20versioning=203.22.0=20?= =?UTF-8?q?=F0=9F=94=96=20(#26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(tuist): Project 추가 * fix(tuist): Main.storyboard를 리소스에 추가하였습니다. * feat(tuist): 버전을 고정합니다. * feat(tuist): tuist-versioning 23/08/15 기준 최신버전 --- .tuist-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .tuist-version diff --git a/.tuist-version b/.tuist-version new file mode 100644 index 0000000..8912835 --- /dev/null +++ b/.tuist-version @@ -0,0 +1 @@ +3.22.0 \ No newline at end of file From bef450fa28f80e8386c7fd0837a49e188c93d455 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Wed, 16 Aug 2023 03:02:41 +0900 Subject: [PATCH 21/55] =?UTF-8?q?feat(system):=20Storage=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.=20=E2=9C=A8=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 28 +++-- .../UserInterfaceState.xcuserstate | Bin 199379 -> 205684 bytes Box42/Extensions/Double.swift | 12 +++ .../{StringExtension.swift => String.swift} | 2 +- Box42/Main/BoxViewController.swift | 13 +++ Box42/Menubar/MenubarViewModel.swift | 1 - Box42/Resources/AppDelegate.swift | 3 + Box42/{CPU => System}/CPU.swift | 2 +- .../{Resources => System}/EventMonitor.swift | 8 +- Box42/System/Storage.swift | 100 ++++++++++++++++++ Box42/System/StorageConfig.swift | 44 ++++++++ 11 files changed, 198 insertions(+), 15 deletions(-) create mode 100644 Box42/Extensions/Double.swift rename Box42/Extensions/{StringExtension.swift => String.swift} (94%) rename Box42/{CPU => System}/CPU.swift (99%) rename Box42/{Resources => System}/EventMonitor.swift (74%) create mode 100644 Box42/System/Storage.swift create mode 100644 Box42/System/StorageConfig.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index c3b48a3..10e6af2 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -29,6 +29,9 @@ DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A222A8B50D500A88DD8 /* BoxViewModel.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 */; }; + DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */; }; DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; @@ -36,7 +39,7 @@ 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 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; + DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* String.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 */; }; @@ -70,6 +73,9 @@ DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewModel.swift; path = Main/BoxViewModel.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 = ""; }; + DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageConfig.swift; sourceTree = ""; }; DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.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 = ""; }; @@ -77,7 +83,7 @@ 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 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + DE874F5E2A5935CC00FC3B77 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.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; }; @@ -125,19 +131,22 @@ DE77BA542A82636500713683 /* Shared */, DE874F512A591EC600FC3B77 /* Preferences */, DE018C0C2A509BDF00FF0AA3 /* Resources */, - DE018C062A509B9000FF0AA3 /* CPU */, + DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; sourceTree = ""; }; - DE018C062A509B9000FF0AA3 /* CPU */ = { + DE018C062A509B9000FF0AA3 /* System */ = { isa = PBXGroup; children = ( + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, DE018BE32A509B1700FF0AA3 /* CPU.swift */, + DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */, + DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */, ); - path = CPU; + path = System; sourceTree = ""; }; DE018C082A509BB500FF0AA3 /* WebView */ = { @@ -166,7 +175,6 @@ DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, DE018BBE2A5099FA00FF0AA3 /* Info.plist */, DE018C022A509B5D00FF0AA3 /* Main.storyboard */, - DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */, ); path = Resources; @@ -264,8 +272,9 @@ DEF749302A85655E00D987C8 /* Extensions */ = { isa = PBXGroup; children = ( - DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */, + DE874F5E2A5935CC00FC3B77 /* String.swift */, DEF749312A85657600D987C8 /* NSScreen.swift */, + DE1F1A302A8BD68F00A88DD8 /* Double.swift */, ); path = Extensions; sourceTree = ""; @@ -355,7 +364,7 @@ DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, - DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, + DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, @@ -369,8 +378,11 @@ DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, + DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, + DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, + DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate index 96111f95f45e8662e2f55e9f09dd1611499d350d..4022600f611713d7c999fb92150eadc0465a14b5 100644 GIT binary patch literal 205684 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%0A)F_XzbyW&2=+*n>^MtL z&>8D12I%BR4dRE5;=!|96O*&(r(3Zl=v$Te-U!q?o z^ve3Bv{&ZZKjhvNdy{I~|B2k zJ6D6)xz^io^EiXyA7W>U?p}Ca8S=QAuU#i7HA?5eH0@9S5c^XL++1QnL+xD;GQl1F zUHv@+0~6daD5wcS2p2)PNWujQHo%{FB&t6lF*q5VB^!hiE~udm3@ipY183k3?gkG- z3&I5xt{36@5UwBL`qvrajxZ}hZo;f&bRiyY;lIb5pz(;CW7o5xooI;Oq9L%ALHeSz zXvV&x8KoUwk6|8zRx}S*-TyoD*f*IOOLL5k%2L-p3|i4VVfB_+bF%XD^`*iNHGAi2 z2r%@=AZQ3Q1Q~)2A%TWwINg-1Pzhm zdZE!|tR~y=&Nu^)|zMhW8C05H6Q+ z;|Z6yo>^x2(C|@(j&S*en?MgI3Aam|i1)8SPLJ9Ta7;+9a0W@|+K+@Y4vGrRCKDn? z=piC$MMVX|5}AR%;@j{E;R@;+3^cZB-L=ifSBU-hHnku87>m8lyI0>m#;TmGW@_CBHTp6O{xf^#%yB^uNSdh=ROpq zh0`ssp{8Lns*vbHgpJm_PdHLZD#neIR=^~9@bdqXptIagFH+G;ir1|zqs^CZFo+cc;#q}ph#?Hnr zQWuF%u#qF#*d1M@(bwo_>|s<9ZXV&DB-{eREv)S#jb7rkr`D0&0aa5vbhWN7G?=sM zUJzZ$XT|4;$LJ=FeZ+2ZvAvs2f81`ep0LJxzc&%QuD>+)5&O%<=w8sfHmuuC4H6|7 z#0rB%8)J;Igj;4e$P!`5dXaFe2)DZ4m}QJNCP)TZK{)sz>MzR}@kZ+n#$m=3W2zAY z7M?qvBiwSry-;TmA?ldsBdoTJMyx^8hcu&2Sgq!s7gww4`2~+-g+kE^EA3Wz><2Yu zPv5RvU(R|8FBBEN@==$}&?}EE$(m#>9Ef(EU4pm{>@G$SuW<@u&W-3P)*zUs#yA6? z%rwqIxD#IGLF4lHgrc$(=X{(D0_@ry7;Xm!k@;!9~2g6 z{Kt4(2#e$1Bm5jGEY5zTi7{c@(0Y^1BsVDt_delJZTGG>IeH)PK0vsA#C1IWPwQ;U zX2rKb!pJE&R4g~6LByMh!?EZl-sEobFtsqXGJ`O>GGGA>ob@?pMP7L-^K& zZ%g<r)j|q2>aEAzYxVHZ>wHFrv4~PRdCe!tzA?o+uc5hC@ zK#0c}VN7A-2y^7WeH^+^07QLx>qZ+>m^j)T!SG(Ma1U6KGDT}`rdU%POpst2LQPNu z6AtOhiS;DmP7&@5;m+3CAX

WQ!IbTNfcE&OY5ipl((y@;V~kSK7@ymXk@C2cF1x_S2MJ!!8l|E& zK9}0)bQAVURGVg)W}0T1Don&Q+cd{C*YpJ8&JpfB;l3i=*M$3qa2E)N1^@2|cd^8)fkRUn8seR4@ai8sKJU*QzfP1FT(vG z{s{I6l#IC9RE^=tgn82CN)zS~&GdeoUNOBU3`eF{>2O57-|qLYs^GBYLCa01w@f(X z55Z=pJ;HEAz26VIWuz@L(_SG}>LznN(>|fE-H(QTz;uu{^xy4$EqvUVh5t=B6tzJ+ z|HO1eYUeiz2WNMKzV-xd=O;}yrcbVRkS(nwccYD5-1blZuf5y$ z_G9j9)}j+McQgB#yPJK@e&!x#m04}p5Z;0Cj)Zq2yffil2=7XGH^M6k&sLieWlR5= zO=2f#?n!vgJ}2khrB0Cd{NJ4XF*-qWC^|uN7~y$)CuojD^LAe2HiSatkwn3XKT(gw zMI3XqIToFuIfn2amF76Yw`ks++&t8rj4sWbh=^OhB_eJe7a-ymKIiZUb%N#*=FvhY zXdXp7LB16_!3R02M`8uI0NY)$2}`9u$+(-d2;WASsGIS=0{W)=^8EZN^EhTolO9rs zU?Fq9xj>s~E~*O_BD^=@5n8*H@aX;;MGKir&1F)9>_YhV4ZBG56zI@A)jZ8S-8_Tv z9SGl%@SOw1 z-QQ(pMTPg7kC@M)wS8s&8m;Y|`CBaX^1bMT2ai4oK5n$OUW5;AxYBF>-h4@FZT$!z z+^DtvL{;~*`KtLB^RI*tA$)Jb_aS`W+SX=1Cp<_XW#K^r4}Vzx6a^fFlQQzN;HsRI zn_c#Q)(kCjVJ^b=x6eg}KJN1d-P2*O7aegNU42tSbUg9vXW{NQR!Yq7ms+KZlTOJ~B<4cYW`89r9> zZ1Y3@*W4eYxmz@7?iMZKW9-e{VnChk8qYmRq2c<9TjI~!QI@_i294c z#g-x3OiN;&XB#Uye3HM)>50ZP_vkda;bQq+7;VY=j?1_!PpY z5`K7XTW;jomYVGUx%>LTy9%4kA1qVo6P9HutT%V zw#<=~kV*K_jg;^tRl)+xLdzn{V#22r9;(2gkWs4y%M{@W3;77155!-nz7cAeRv*0HY zUI>tAx)taDhwVIgITv23CcZSx(lbbSp9tO?X5Y|bx!mdYCd(DePnMr8S1rF-Fe|{} z98(EDjqsR{&mugLcKTSZ*L&}$s^g=XCVP+)UDxS&XuV{C7 z1HIhe3Au{5@D*bAICUr4Dh9v^w@Zh1;gFVkA_%$qE8E>&FD6r$2o<+S?Kuwg5FXLj zP`8!1Zu63uN=p>g-;?ljCEucdYa>*J1ke~gNY2)~4`3G+)UdZp5nEvRdHxNx`y z{Vh%0!AV!WMW0IT86UMLh)CI4{DWwA{{B7v1N<>`qWgS`@J|!|nGMYM*seR5@x^=w zTXe(iht&+jAuKj*gBN0IgyUs~+9rv|)WO^hzs<_WVLSF0tzcJLgDW2%LA6%!37s#-)=2l;{Il+Ne>U#VA^b{u|Eh|hI^+3-uHGs>QZP7)l)+h~3|<+* z;N2e#UeUndr3wtw9}EG*z(_EfVLGhj3w6+XoH<=(^iy0Qq-2hcjk-g1!K{^nv|+QUKET$pR%{2ABm1m;;^w z^8s|>16}w)7e3I14|L%JUHCv3J}9%#6^7~V2-*P)=nr7C?#QS6U=RZmK{7y|-G_q_ zU_3yc-H}fB%>ZTSz7xC&-U9mp%F+D@fKI#DfYSgv?fyCV8eC-E9AP!6U7l+||;SOQi8*w%M9_y8OQ(7o>&@EQ05TmavJ@4*k? zGQ;@E0rK@j9)95<0z?An!4GBkO9IIN<@Xx{askTk2V4400rS9tysRCxe$s*1n_PzuVyBmkLJ(*Wv_Y8F7f zRm}lUfcannSOlH|=nGWOf@R=&@B&x~R)d$oS^yoZ)`N{;GpGjJz{_9yF$GgKAHSDg2 zoNCxy4H?yFYj`0SqelC{OS2gD1^~I#TLENJzX~9adKZ8!>UY5h;6v~+I0TM>W8fq> z4L$>?C+e>N>aqGF_yJr2SHW-KcW?vz1#W}845N_&2jC3c00%sPCqQ4NX$LxjE}$Fm z1uCEg24Ds~K@jK#`hrk^wxWp#LqH-(2FPD?k72aPQ>y@u0Q%LA1GxY?)fRxg;8SoM zpnTd>7^dceXTdT69qL{HD5LHgK)Sj=!A*wIM}t&=boHFS|F{eFfq zcmq8!0yFRj$isj<49LTPJPgRg@H2qE4F7;Ufq zl*Np)m{Ar>2Y~dkvcXu8J{B|>O9gleJOfZ33(8~p6~N|}I{-HDhYkD(0ocVq1q=rx zz)N5&*bZI+sEa+FfG6+*Z2-#EGaHnGaxe)@0kB!mFTr{6HMqbq0gx>q00e;$&>KLm zfEU3UuntrK*f0Qc1wyVs)Qv#YjX;z?5V{RS-3Ub82rK|Q0m>eTvIj!nfzWqQcK{m( z`2*w?guH^FN&{0w+KXI1SD+ObF~4g7ia> zehAVJL0LlPfn@;sgdm>~4oz2vVvg%^|BYr)C)H41zYxlEqlS1 zy-=QBC{J&+t=<;U69j@_fO7Ok`n{2UZ=~NF<>-A4ApPD*zYo&y1AX;L0w_x#)X6@m zlYOAKK6?Q4)8`QQ1RQ0UzTJQkKwo`Pp1vqg-vwYfSOHc6*rxAIhUtfN`@s(VoPjGq z9{rFFriMs z1;8$$uuCX(6pFM%k#=Y;jM}`h9?MM57GRhXC4R z^icr2Mt=)_WtbQlfQ@1xZw%T)3=?frl4CIX& z00x3gFb6=Mn8V-~hKWUbu|Z%MKsjO|e=GrW!94H`fQ@2NmROV}wi0Xro4^(TJH_q> zC|4}X6}u071TFxY{_o%hxCQjowy#&^RDge3TQ1&?3B5pf)1)%=K z{lqZwJTQSIfb`-~*7*0pd4Tp6e;ND?P^S2s0Od%K1JtPm7oY?ja0e|wXV4XN2Pj(t z%9fx5RsdZmi~ys-7?1@}wgi+dp#Y#BCCma(f(2j^fDIB*mV|X+J=g-a0hA%(Rqz2o z9ZL8HdC z0*nQy4?~de5acrib{&d)h6VuWZ0IO}vJA}tD9_MB0NV_OE{CE#Ls6cg1i(H+p8!k2 z^8n=<3OfyjzK5c0L!tAbpMc}wBsdMe0O!Eh-~#v!pe#f0fO`y+$O7m*5#>m115k!U z=syu>8#0rZ~;{U_Q$CKw0C1L!}o0zl40$eB1Fzy^tn0op<$Hv^W63U;1dy=55q=VoDI0epv&%w609liv`{YjnWKM?6$&fi2`cFO&z5%FP$u|IGO@^$=RMxv#CXxXKZ~`ts z2~fv|X@C_#ufw3fVLJiR8wT5@z)mT>K_nOm27?%Ya-_gEDK-Gxq>KaOK|YuQrh{2v zHh_&%=7SC3HLwfp2Je8q;6v~+K-p4ImK5Zj@&iD-NI|0-Kwl6F!a+Pp0;of2C{r5BlZNu7!3Jq4Pg*&c4W0)pz-q7t zR08NfZ8O*kUIwoM$eae5(++`80OU@C+-Zbkjk19X0Nsv4zN3)OXb*sUMkj(2 zFb&KED9`9QU@>?epbVo|1K4MDC0GwO0+eg?8{jSQHh2&01s{TMz*T@YG5QaHb}{-k zK-o|gm~=U40a}4hpbO9eGk{F#C`UTMy3A{iXfHrUQ18RVB*^IyfP&V5Tfb?w{APb;v+t99UMF3^9 zm4P{69zZ>^tpL!!Z4E$qY$%Tna@n?mJplH!q3+wx1L)oM9k>K8gP*~#;5tD0#ySHx z0GY?~0CixjCxF~zQTDOz0qijr_81HOj~xMK0oZ-)#{lVNpsX3FcNwu@7#I#l0+cCZ z94H2*U?P|Trh}QF0>CaAO90B1u^g-fC|d?>kb(3wJ^`PCui4z2!cUhfU;$WgGi7FhJg%#x|E#;+&ss0Q1?4)8j76F~pj?|}EgKCmA^=4{BEeI9%bAa^$8&W7CCs9V{v zM>gz{{TsuKgZ{^%KN<)9j)N}8K^NnY-nehTU53d)oyze8Y5<+(piDVI0OiPu0I*Sx z6~urz0K4Rj1~!lhP_J@w0c?=746FdFz)PSCYyg`9%9ew&tw0;l9zfn)Z{PzUcP`}4?F0IQFaViz2Y^9fFo*>xdoJoi zZW4eFa#7E7Q6F;8f`1rhJklEvdyUTkv%wQNr#%1Z=e zKq;6A(022tgINIb<~;$P1duxqa_3b7=sj-}fXsPY!OH;kDi8H44`t7L3+w^VLEa69 z$!`aGgLHuO@?o$1Ljdg{{~GuM+yp37fefG=1sw1Io}e{o3w(hJXn_Hkfj>w9qrg~@ z1yFAa@<9=RO$t!90+giyc^51NF96h|f|o!QKzRyKj|w1H!EW#|_#B)AXafb`g6{$3 zE%*ui0w8w*xwf;`^Stl7=Ira7ea_H;&-jvW(5XX9^ym;q7rN7vNbIOXKkTK0d+HE_ZXI;% z;I2B@K?k?fVJ`;xbpTr%n&~k7wv+d_h<|vhyBpC#(deDNjYJP>qlIlxCQJSQ~T- z(mOF>q0P>AA~ zeYdjc(@mdla&@zVZlBPU&U7V$Ui6_qgNSAr`gQx6*~r{&KJKd9V&v|od$(U%gMD-} z|89?hpnFEj(*)1!u50&QT;m=Oc#KXFA>39(a#E3obYvhm`6x(XictbPi1?Q8X+bM~ z#0l6|G)boPw~C>d>sV6-b9~X?x>esy)u!Pa=4pb zRj5uaxvO4%=*KiRVYZRx80kHc4e>LP`a~{e zEgSd^-$JA={y)A1kvc@4iMgGS#UZPv?Eab=C^e%?G>0Orc=+?V3 zAMi0>)0j56q24m})}wa>J?TwfMll6hdz*XjRmj|X12Xrve6>V2RVz~_0^;AHFW5E2Oau82!ej` zNXfhSZu|Le`xV6e`xT=kWhjUF_mj1sto>x|Cu_g2Xv}vs!?)0{C2p*r-y!{Gvx^%+ z&_4y9*Z)hp5zBODGKYES(SIEq*^F8C-@zZatNwdAiJR(w9^Lxu*5AAbxX%HpNJ|DX zksaLz~ z^8oiWU<+~&kb8jK1NN{F`xtN-^BmV4Eh@_a=Ae{zf zM2|tav7WAjkZwW-I4e2i{GKj#Np5l#fX=!07t>XwG;GgP0UvJaid zdN#3zZR}(>`#8uEj&U8Chu-Ecau1bzsN6$!AL_P-+Q%^a7-s&%D$*3|8gigcj(umLal5hBqrnILco#~2R!+T-}!{@M&#VqAl>}2>lHn4|3(P6l` z55L9@^cemxIt^|_YrByM?nfxjFOb09D0qAcSLo}d&F1BI>J4TXu|jS21eMy zh&H&X5kFz(Bjg-$0Jl5xZ9H$Jjw2(Pf-WQH^9%ZnT+L>FX9v63%YIICj*DF8D%XQx zRD9kdJsEM6quwDWdC+Z?E~9E-=A#<$A)lhpD1AohGpa4!7|ICT{wTLUDwaveJ8C*J zk$coy%zM-(WFEDZ?YO5=yODd8?xPN2_M?+g6gwZ?70(;Jg$uk2f-wn6LUK})0X@d# zA}<9fL=h@bnQGLe4)w5uG2ukelis+;F@uOkw=uemiDN#CS;k8A8M7XJ#^^If_AzI; zgF7DckpFnb%ODsV@CFG;jJc1^j?81ter#^cer!Psqx;wrl)?NN5L2A0d_Xf=VD2$(X-`KwW5+S}5Yr1;V`Po-q8M3Ye8(|y zOl1acDrOGza6>VdgJ66@^3xE{8$W^79OFEf_?xTfG5!h9aZ9mg8T%#)NJBa@Vn?xd z6#EX9sLw}y!e@NVw=_YwSY2YhJGL)_a6_@f7>z!$_7^KxthvXoWGB1X$3c!DZ|q6z zAXe^Jxnm#VmSUeGbF6#vm|#LY;-mY7B-qCUGni0^9~sFCJa58_Aefk$a#W`lbDn=V4~+wT*EpxvXyP1x-$^ymZ_+n>hs=|{$6ZZoh1`>LpY#*HnMw9B$^0iR z=JDXxxQxlMqw@8alQ*)rl)b}VtaY|8! z8q}s94f%*hbf6dg7(f)m7=gV^)orRSQ)glJQ&+JT^Pj5E)Zfu(syAFs@Pg~s5 z^sYqElY!_lU61MGh-DIXG<`n5u!QCO%4+Oj`bFH$baS45gS*`4A-c`bWrlapF!ve0 zi5Xcj`x&{>XGQ_!no*uQe1p50(To4@Aj9YJQJ9V?lY!i zA2ZBg#NZoCnch9K2fl}y{Taki^qDydxn|B_Fz!!YYw=|_W zKM+P2y3>>1^kpgwS;}(U&Fpn-z)ogwL6_OyJ^KQGbB!C^MW5O3XtrE);`0`{$%k)X zPGO26?;Q6(ryO$6slq3i`u2Wb zGj}qxn9Blu3v+duy9piUZeu6*Gj}ihIn6mPa+#}K4}y7m%=7$t>2WvnvhWT$$%Ah5 zbeX5iyz11X5oSM6k9pss!#v-{JRRn>!QAH!Vj^)&<7Z|w4?CFWmgc$jc`K21o~-j^ zohR!&JD7I__cZS$vd@!!o}J8dKl3wFnPzy;eEsM9nfYe5AUWyKWq~dWvXPgfl%O>4 zQ-Mm<$1N@Rm`~Ab!B=!;0MQI%1Y;S`1SVle3*6BH9Tu4Tf*tHaj|GR&VSx?{PGH^( z9t6R{1SBRIDS3;uWI(Tl@-8(0g>GnJ8Dw2po{Ch#ce2n97S^U74KVYCaxPrN0sakw zUp(&@9e??T9_aE*6hqMGml&opgIUaF0l%=84gAJdwzHGV+~W~Xc*g4>SQL*p(QT0~ zi@bYLZVFHcvtLvSeHN8Nu0{3vl6L$=C&KB5yo(~~i`9XuRH@U|H9;45)mqB24 z!E$|;%f37t#qb?0FGD#hQibZ&qAm?E_vPOs^YWIo#_X5NyfH{AX5m7KuN zSJ>?e&s(AEiYVOFiX{lM;#XF)89i3$vEl%SIf@;vIElTixQ<>c?r&%}R({GCxTTf)tZarpEA?3^`^x^<-^z)^F%9>;ayIiY|CNhb#x`~$ z^U6K!;~;XclzXMzE8W)0Gdu}`U(-{bZ|R5U{i^G)H-cc5n_Bf2X~{q)a-zqoA{3_- zWwE1GwW&u#KH?KT!wy!tomB%F%n(L0hH>b&N|#l0S;<;9;FebDvuX$WtkP$d?5nO~ zf2&^bItW(BBR+{pN(xf*HhC$4%&X0Qby3WIwcM-aUM=@(x3#)5jp@mB-0*6#&10mvJ|1ZgQJ{dBlI{wpN$5 zX)*J)?r5#wL2GlP&su%f>a*6~*4E)0zQf(DbvJ8U(H42vcBC_MuQm6z!x@RpYsX^t zYbP)nx!3Bx)@`jd`?cqSU|k41UsoH?TW4qMmf@z>o#YJXxyV20u}+V5Pk7F&AXx9) zUZ0#)q#+#{$&4MWuSq=`@FBj3^`G+&<<=KI`>auh06aEMyZ~ za5w9H2kUpU4|&%g;TUqSH}~~-xQEQ^A7b|F&3^q0h&)e`I z2sXY&G0IVqD)_E9)<=(xdTi8VqaGW-qbc9hfiSwzot{Ku4;$yP2)DD*?QC4lS~j5H zMtwGV|HiXi;%}~T3!OIJN48DAi%ltc7q_!19|b9l%$rJ52H7{szUd=A;WNHK?oEx6 zds8#?-_(-Un8POD?517Z2!h{I;Ca7&iCz5`i(C3_CUel~H+S>fIySPI-`T+*9OVS3 zImbo*;&l*gPDX0n&gOJvCM))`S+~u)Y%YP>Z?1`NVzc>g)@O4g^x3S>X4yA)CJMK+ zc{rmO%XlUd$25NCSJoi&X0zYCi7m*zS?v}x10TTxwp%`UGD9paa-H%WBUZmfBT=9?+&xv zVHP_)Z^vNfvV#L0#>{r;wBrJHwBsgrwBtSxdCZd_*cqQh=(RHisnKm`Q9OTVHEL3u z27HKaJ3rxje!#8n?1o#~8HqkS_1P)c&LOztopV^r27Y5J+xde%?B@{r?YzoA$h`A5 zclj5&cj~_LDKD^(Kg|D+a(qW$X5)E(=(;O8?@@}flt-sswa{Z%BR=CxzTsQi(w>fV zrYqgCgIzP3#{w3yoRzFbw_UpIGWT7lIE&fu`Wt9b3pUG8{yLNbvRce6VudB~5v zyNgg9xp&v0J`It1x7qLhl+XDJxp(Wn+imSO``uI6!e2qKCjp+f=Oa2W5_hy`GE_f8~^X~?`+=DlXW*X;Moy;ttNa_{{e zx3$+k_U^{~_r=G2_nGBBv)Jc(`_^$1H?=?D4a{u6PWw}1NBgs4NBeV4$Fnb=e=o&&*{3i_mAkTiUPBetq`KzW*rKxWR4i@qouX zKkyE6ACUWi+y@F$hVwRO%>K|IqLKTM?uXpg zA^SLFABW8U&>hN9;a2TBqpGA+u*SX0Z?(-lBjs(0x0uqyq z6xhL$vQ(rp)u>Hf8lc+|U5=Rh5qEkd46{Gd1AUI@b3~sbqnXMwR^o1sxaT7q*^InL zcCZV%kDTWcmy!91*&n&VE$$-s5#5ittv}OHoX_db6g=-j=dbUm!m)O6T_H@9!IA$lX)y)5lh&_9u8utM~`tDvp;$P zosQn)We^-oh3v=d?^s5%kezqQO+L*3n5@UDQk|N}eXJgGANvrwkGZX5`XB4eSXOhA z7eR2`^N!cz2i(VTw{(0o;~0YXj=yO7!6Z)KJL=(d3g8iN7NpJcg?}@<-MeY+bn8h4qK4JDJ z%>IPgpIDCECv-ot7PCL$MownH_i^$&Jn!Uu{=j{lbW11y(WyM-N3T;wD2{HY?BJB=pK>>++|8-hw5KC>a!R*T-hE1!Q!z|p3e%a5E~m`@ zlrE<>VBV+Ba2_{v>Tj-b1G7JMj|V&sg46PzmiM%|pEmc?GM|?Dw9Kb7;jT{G#p!pb z#J8C3X>&Yn4yQfuOlpeap3Z#9H|TT5w{WHnVd!wCJN9#?H+|{PD8@3LiNxU>IkO(m zKeG>abLKF|G2}C6(e2Ft->u6T-@{pVbT&STNRBRN)1b@QToj`QwW&u#KH?KT=PMfH zp3cg9R^GGSh(PAEGM|;MK4jk`KKkDZw9IdeQ`4(B}YTo3H&+*-D>9evL2<_Krd z;hg=Pv!8R<_y;>V_mmgB4ubP~oqrSaKVO&_I2&by)W?f8k# z=ySe1a-APSEDLZm=a;gARmgjO1HU2ndAZM@;56obUgq-`xy%)=qx*TgIDamaxs;!P5hloaT8S(nS^e%beM+3%jqW`DT?`drrM zvObp^(S$I%;BGGa1}^ueAM#!v%uwXMJcC)xLFUV5e|Zs0SdQG6b-(PkE}Q-3he7an z2Fmdrp7-~B{@^O^=B|wiW$w)6RD+|88>{Dp8=u5*(++(*Bw2}y#? zSIz#a*+Rr|PV{#U=D4?nX5&%37UwZb&S9bNm1#^`jd6?$CjOjjc4 zMQ?^Nk}Tu*XMd>@==~j zxSQ)Ws7*cOz5WrOAouk){K!wpeBJD?ccD8yiKH+6na*#R?LY4KAMg3+1N_WC`uwwu zb!=oaThZm8KRJ#L|D5Flm$=M59`Kl_yx>(3+|c8O=iewqQHoOrcX^`%y4}#_#z%b1 z_xwO>+S38KZn&cx?&!v7+|7--_y%q)Vks+F#acF?-;KkV`wf|Ioa8j;xQNU*+|`Zi z+z5i3W`8peW_!~dZ+g$o)%cm4`rL9)x85NadGRgW(&d)@+|uEe{oJyjTlRCSE}!!i zjcI~jw_4B-cXMkTwm4Ml%e#@5+7GyzkCq0W#lR%re~5UH5cX z_q*${kGp1Y_el`k%YvQX`yS7`w}`#Cqk9i{%u{r_|0c;vMHVA7TCvWqsI&cC<(ChhfP5up4qebXyPge;9`wd3Zhu9tGsW^B(=g z2;9dbxAbT&8`y;J;E^7Wj&O{VoZ%ei_~Z_n)5sJq&^;X>dnRvZK!v^LkQ<(&+G{0+p$T{XF@Y zPx%5j_e8HJO)&o_LvS-s#xRbF*vFHp==MaHC*J+!H@0E!Pj+(veV+V@Tu=Vyeh@r; z6F2iT3CT%?yie1S5xJkr{j@lxF!!f2KP^uss!$!>pW4M!ckt8nW(Uvy|NKWh;Tf-k;JKYV z*X?-%(qit<^HKn_f3DB-lIZhXpXaha{|tBY+}%9?iB5#mjUGhOmjT2w37Map{d2Q_ zJ`=g0%l%yL=e~pI_VIi#H-g|r3W{R4FFfyst}ixm7I*aGIybq^WAu2b$IJL6A}MzC zG80+JK~D0J4?B3-2zT?+oL@Gk8O>>lZZCCtIS?~{>3euNiWu~Hsn1J&UfSEsHSA$O zhj2G9k8=unUtZuZGpaI%4OqR^xeoEO?zA zH}$$U^=Qb4e2E^f^?0qvYdv1Kqdn&MIud(%Z7;8*h-MBe(Bt(wHsWqxZ(}FBIKgSI zaf`eB%YQuO1+Riokeo~uq9`RO&HGfKGS#R_9lqf^n({p@Xhj=-f9i!i$cIwaV_@7R5U-R#306a35bAe1mI?~)t4 zO;`|J6BeZbpW!AGcEGz6cA+~x>5YyF%{!s@C-nY=-k)$Hap<0KIty8icPG3Wgc9kT zC@-a`M0ILW7qd)ceu?x>^b_8jNbf}6ok;IQL(w;p_a*YaM6pa_HuG43{)v{df?qku z(;$@CdlQ#Huf$*BJ`=mo#4YiyCH9`g-ji6z#5yMK!4RgfiJk05kHlt}_zV~M3pbYd zA8v6M_m(6PX~~4WCb8EfZYhabCo$_J1^9q3XhAFNI!SwENg_)UvrXbVNupm8ca%h* zBx`V|Nn}c5ze%=nh$9@sttB~)-bpTS3AvIy2|`Iz;N3|-MCYWv7=*bdHP@u(nsh8v zna?WhE~$4WbyG>rAn8H8E2(!SJ&8Fa)j#P~%pj?EB{hSjW{~t%5K0!}O%jrXWMm`{ z`FW2b6sHtr@qH$%O+6YQZ?Z;wiu*|BCX=-zj4s$$GB=qll4#sUvT6LnA{Mihjr_qL z_G50z{^U63luVCgdL+{$*)8-)rbjY8lE)_zNioOdX-SX$CeKQC%r<#J3R9GdRHFv9 zsLuy{%qO&^8}^XAH+`{>k>Vl$@&9+f2tp|n@(zV5MoG%>KIQp>7I=0_&ra#tDLp%-J*PCQ zlmi&eSj;Kq1ST_;>HLiMr(DYct_Pu1`lfPssk|$d{iL#=R5htXJwBr;?a?b$2fRO( z{iL#&R6`iXNW44MB;xSSR5O@`U8UN~Nqirv&T)~yaAT?NJGI=Y zXR?&#tYmc%ddsZdlHn~G-pWBv`ZJ0#j3buUK`2c!vhyyvkuyy}>^4m?%sWjP%F&RI z_=L}KQ)wF01o_jrsWh!=i+pLeb0-MBZ8mTF`L})dZ_nmv5K3!iX?=@nGmsfs)0$UW zS<`w(+AegbC%x&1yGiS2(oSa~i&=)=Y4uLK4)09+2YcAhA^zkTH-b>Q_~@I?Eu||> zWvWq=I_Q{Aw{*Is`w=i5L^S$l@Qw`Lkzpcn*l&iP z`GswGUk2~VaE@Et5B%F)^vsx#Vz`}*tue=po|#epj3dw?;}kqI<22lLM!U_pgrzL! zH@qj~PIjYPM%^-cXU5|}C{uFGEYrv6l}WEmO=*sPnK}@LeP*)HOgd(Y#LZ-S5`;46 z!3;8Y#lMzW#>{Rma}-06HS36l5eD`EgfS>@bTwS?n-NJ=|3m z{j+?-cQm5~t!T@ScwZKC$g&zc%5P7r8mn}qQ+kOt=JI{8UQ~b?co&}-oZ(u&z(~<#svgaTtdB{g8s!*L;)TIF* z;-0d*r|j-2dvjXShIaJDe6pKG_TSjbcK$%7>@sDSDZ5Pm4pu1p6|QqL2<1qLJUOx= zPY!u<$djWy=8?l3a(vELG^Pn|C5PGM@O|bOz(ArH$6V|vhaKfuiW%jQE5}+kAYTso za=4=$?kI;l%5jd1T;?kOa0|1`aX$#XV{h+#%5ePrJOA=J2)*m}-;GZql9HT8$oTH} z{6K5W=-u}8z%Jj7W*Bz)u3f$x!*pgchxz=%5|*)pi`Zk%H%LHYl93kk%W0oEv*EsS zy04t>D`!#U&S`HsThI!#%PC9Fj`TvFoOCF)F9$e`z2-d2 z1^(g+k9o=q%qW)`NA zEV*UL{WG(f$3hmfl$${)j~VCDCy$-x(IZcP%rehVMlc%B$}=55o5#=Q(IL-DR@;6Ol8~HKq#+&e;5*5emjV=`D8;GG z_t<$pGs+juFh(+g$;g&(2EN^Vi!kSWD>#lk`L5!-%y$b}^8Fix^1q4q=Xdw{y*I!4 zw$8V`d|!GzdRK|3m#3NtDwSHX;ALB4|W6)Z(r%2SD|)Sx!? zXo%SrY=pfPw3mY3SsMI6!ul1~ukcTF!`us-dtq}gEKA{`#4??^*g;`A3d>Pgj>6tucsFKI_zdT{#8v*` z7I%VB5wj>FR}s02$W=tHB61aR2SwaLk&0BII-Xxdzash-(XYsM{$LOLIK@RS<2^;Z zr-+#sdB9_y@;nF?wdMPCN@v9lm$tjoGL@F8v`nRCDs5+_t5O5IE8Pxx zN=G11X?aS^Q+fjCQQ90zuV58xaf_vQVm77EbAgNeh1)Lugy*~pLS;g{Npjq68FyR8 z-Ig)4GMTZbG6j&ajErUMrp##UrA!PmlsUt7%)QJlyrXOd>SDHK8{+QDPR8!a%2-y$ zvcIvF?U+&7J?!TY_F49CuHm_5Z*z|aJmx7nyq}hLD9MMoqxU;vKJSla65jj%RNVFZ zD_PGLcH^Dzd*}O}|Gwvzdjs<*=Z4EA7w;=q5xXi^m3nx8x%Tv+ zCw5h?H^Z2Mn<+OFH&f2dlyfuXeDCF!^DAzp+%ERwJ1=K{<&JWK)11RD%jsS|8F_Ip z9_`Zl%0gl;4Ng zl5hBqX0)Is9gw$TXL=!T#lFm7F-usAxmNs*t+?rmf8f3vvD!olQGLRX$Dw$s;St_-n4P7y>O6FB*1fv;8ER&eRbe3V)l~!Yxl{T`O z-`Rn=R+6!j8>@5*IV+tHLX`_*PL<11fyxYI4Bk_DJQMMAmH*}{`c=LegsPOF3e~7V zZKm-H=2gY4s;me?Rqd^63Q}QbRnwwp)iA=*v1$Zc*pHo8^}edUg{r=Vs@_}Gd#jph zRr9QRCkRzbNl`wbF-`a$&#m?oc3I8ys|~@ds!hcntIc9A@>P?sntat(;SQ^v&l;UD!y0b2hIiKJ$4Kn0hP~B@ z!%k|5nDNJSdbkr7>MW#?UTQOcPpT9<|*;?Fj6>wrsU!t1VmY(Trt0c2avXvzW^Q7O@JsYs+2x z5bnPAMJ{ude~`cS6U?>t3tk5yf3GrBM~*tpXhAFFsN**3xQ#lU8HM|=<9&6!ua5WC zS;7W<%XK`r&K=xl9rLNs3kNFOHK9=X>AGpc`!;7LBmWVo&}V&-^)tKvYz#3$=nMP&;#CmxAH@lM8ISmQ z#+T;!r8#~%fyqJWYj^aGy?&DdJ-f> zmG2g@Gzc{*f`6^ahcx0dzT_KpZsJy(n12)VZ_<`XoHGIEbA$J<2)Ewy9k=y~%Cv@h`eJGn-~+(<~85 zNsgOpre`xfnpLJMwWv#d8q%01{75Il=|(Sl(~kj+WjeAqTg6&7@Ecp%&L8YyKNq>o z6|V6QxA2WNv(sh|c+8U^^nF@NV!q$^U>ctHy{^p@k_Y=}UYt_s)VvCMG;e?%HE+ac ze8E?=qz!sC??4#3H6MfLH=o5E?7jJ7mZDqpUorpYJNc87oZ&qBG}ov3|8w2I{kBLz zMzWBdcgamY3R0M2=+~k)^^m#62YkdQ$lXHs7JkpP_!j$UVg4=R*vzFM^h10+?+0Cf z_=yq3GKneZ^us)sp~nxaSi^cYvYUMz+zrpicx2FSPbRz=YTKC5MTaRWcGnvDD^l7b6Yq?sxrPgk#^ &>#O|3E$;F! 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 diff --git a/Box42/Extensions/Double.swift b/Box42/Extensions/Double.swift new file mode 100644 index 0000000..c539a74 --- /dev/null +++ b/Box42/Extensions/Double.swift @@ -0,0 +1,12 @@ +// +// Double.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +extension Double { + var roundedToTwoDecimalPlaces: Double { + return (self * 100).rounded() / 100 + } +} diff --git a/Box42/Extensions/StringExtension.swift b/Box42/Extensions/String.swift similarity index 94% rename from Box42/Extensions/StringExtension.swift rename to Box42/Extensions/String.swift index fd1f378..f04a1ed 100644 --- a/Box42/Extensions/StringExtension.swift +++ b/Box42/Extensions/String.swift @@ -1,5 +1,5 @@ // -// StringExtension.swift +// String.swift // Box42 // // Created by Chanhee Kim on 7/8/23. diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index 3d378fa..6deded0 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -47,6 +47,19 @@ class BoxViewController: NSViewController { extension BoxViewController { override func keyDown(with event: NSEvent) { print(event.keyCode) + if event.keyCode == 1 { + StorageConfig.shared.setThreshold(.percentage50) + StorageConfig.shared.setPeriod(.period10s) + } + if event.keyCode == 2 { +// SdtorageConfig.shared.setThreshold(.percentage30) + DispatchQueue.main.async { + StorageConfig.shared.setThreshold(.percentage30) + } + StorageConfig.shared.setPeriod(.period1s) + } + + if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. print("escape") menubarVCDelegate?.toggleWindow(sender: nil) diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index d131b10..7a7fb9e 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -38,7 +38,6 @@ class StatusBarViewModel { func startRunning() { statusBar.isRunning = cpu.processCPU(statusBar) -// self.animate() scheduleAnimation() } diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 358a56c..e3ea76a 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -10,6 +10,8 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { var menubarController = MenubarViewController() + lazy var storage = Storage() + func applicationWillFinishLaunching(_ notification: Notification) { menubarController.menubarViewControllerInit() @@ -19,6 +21,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { menubarController.menubarViewControllerStart() // alertAccessibility() // hotkey() + storage.storageTimerEvent() } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/Box42/CPU/CPU.swift b/Box42/System/CPU.swift similarity index 99% rename from Box42/CPU/CPU.swift rename to Box42/System/CPU.swift index 1d31df6..f7a8dbf 100644 --- a/Box42/CPU/CPU.swift +++ b/Box42/System/CPU.swift @@ -8,7 +8,7 @@ import Foundation -public class CPU { +class CPU { var cpuTimer: Timer? = nil var usage: (value: Double, description: String) = (0.0, "") diff --git a/Box42/Resources/EventMonitor.swift b/Box42/System/EventMonitor.swift similarity index 74% rename from Box42/Resources/EventMonitor.swift rename to Box42/System/EventMonitor.swift index ca7722b..81234df 100644 --- a/Box42/Resources/EventMonitor.swift +++ b/Box42/System/EventMonitor.swift @@ -7,12 +7,12 @@ import Cocoa -public class EventMonitor { +class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask private let handler: (NSEvent?) -> Void - public init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { + init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { self.mask = mask self.handler = handler } @@ -21,12 +21,12 @@ public class EventMonitor { stop() } - public func start() { + func start() { print("EventMonitor: Starting") monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) } - public func stop() { + func stop() { if monitor != nil { print("EventMonitor: Stoping") NSEvent.removeMonitor(monitor!) diff --git a/Box42/System/Storage.swift b/Box42/System/Storage.swift new file mode 100644 index 0000000..8c55f25 --- /dev/null +++ b/Box42/System/Storage.swift @@ -0,0 +1,100 @@ +// +// Storage.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +import Foundation +import Combine + +class Storage { + var storageTimer: Timer? = nil + var usage: (value: Double, description:String) = (0.0, "") + var count = 0 + let gibiByte = Double(1 << 30) + var config: StorageConfig + + private var subscriptions = Set() + + private var availableUsage: Double? + private var usedUsage: Double? + private var totalUsage: Double? + + init(config: StorageConfig = StorageConfig.shared) { + self.config = config + + config.$threshold.sink { [weak self] newThreshold in + self?.storageTimerEvent() + }.store(in: &subscriptions) + + config.$period.sink { [weak self] newPeriod in + self?.storageTimerEvent() + }.store(in: &subscriptions) + } + + func checkStorage() -> Bool { + do { + let fileSystemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()) + if let freeSpace = fileSystemAttributes[.systemFreeSize] as? NSNumber { + availableUsage = freeSpace.doubleValue / gibiByte + } + if let totalSpace = fileSystemAttributes[.systemSize] as? NSNumber { + totalUsage = totalSpace.doubleValue / gibiByte + } + if totalUsage != nil && availableUsage != nil { + usedUsage = totalUsage! - availableUsage! + } + } catch { + print("Error obtaining system storage info: \(error)") + return true + } + return false + } + + func storageTimerEvent(){ + storageTimer?.invalidate() + storageTimer = Timer.scheduledTimer(withTimeInterval: config.period.rawValue, repeats: true, block: { [weak self] _ in + guard let self = self else { return } + + if self.checkStorage() { + print("FileSystem정보를 가져오는데 실패 하였습니다.") + return + } + + if let usedUsage = self.usedUsage, let totalUsage = self.totalUsage, totalUsage != 0 { + let usagePercentage = usedUsage / totalUsage + if usagePercentage < self.config.threshold.rawValue { + self.cleanSh() + self.count += 1 + print(self.count > 5 ? "캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요." : "\(usedUsage.roundedToTwoDecimalPlaces) GB", "Storage used is less than 30%") + } else { + self.count = 0 + } + } else { + print("Failed to get storage usage details") + } + }) + storageTimer?.fire() + } + + func cleanSh() { + if let scriptPath = Bundle.main.path(forResource: "cleanCache", ofType: "sh") { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = [scriptPath] + + task.launch() + task.waitUntilExit() + + // 실행되었다는 것을 알려주고 싶으면 파이프 뽑아서 하면됨. + } else { + print("Script not found") + } + } + + func change() { + config.setThreshold(.percentage30) + config.setPeriod(.period10s) + } +} diff --git a/Box42/System/StorageConfig.swift b/Box42/System/StorageConfig.swift new file mode 100644 index 0000000..1eec523 --- /dev/null +++ b/Box42/System/StorageConfig.swift @@ -0,0 +1,44 @@ +// +// StorageConfig.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +enum StorageThreshold: Double { + case percentage05 = 0.05 + case percentage10 = 0.1 + case percentage30 = 0.3 + case percentage50 = 0.5 +} + +enum StoragePeriod: Double { + case period1s = 1.0 + case period3s = 3.0 + case period5s = 5.0 + case period10s = 10.0 +} + +import Combine + +class StorageConfig: ObservableObject { + static let shared = StorageConfig() + + @Published var threshold: StorageThreshold + @Published var period: StoragePeriod + + init(_ threshold: StorageThreshold = .percentage05, _ period: StoragePeriod = .period3s) { + self.threshold = threshold + self.period = period + } + + func setThreshold(_ threshold: StorageThreshold) { + self.threshold = threshold + print(self.threshold) + } + + func setPeriod(_ period: StoragePeriod) { + self.period = period + print(self.period) + } +} From 4e0e91dd295bf09d1e9f9ba4ba5ce3f24168615e Mon Sep 17 00:00:00 2001 From: chanhihi Date: Wed, 16 Aug 2023 03:07:07 +0900 Subject: [PATCH 22/55] =?UTF-8?q?build(xcode):=20=ED=98=91=EC=97=85?= =?UTF-8?q?=EC=97=90=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=82=AD=EC=A0=9C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contents.xcworkspacedata | 7 ------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 -------- .../UserInterfaceState.xcuserstate | Bin 205684 -> 0 bytes 3 files changed, 15 deletions(-) delete mode 100644 Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 4022600f611713d7c999fb92150eadc0465a14b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205684 zcmeF4cVHC7`|x+RT<^W4+~w|ay(V;!-aDZq#E=AtgandMrR*rumEN17NkA#mK~Mo3 zRjR09K}4kr(iM1T_ih0V#C*f={SR?Bm&?sOyEC78%FHu+J^Sb86c&X-$1#B67=e)( zh4C;xChBY-lwDAmlb_eco>7q5CkOr3-d>d7zq38R=d0P7MTII1jCm(rA#at|JbP$% zR^8Z#j$i^z*deVbqbQpOYn8J5m>82_ddz?su^<-0!dL`L!BVkGSY@mVRu!v;b-}t~ z-LRLj?pO~j9eV}Kz2%{jfr;2pfit!^UG1u!-0t>@93IHV2!F&BNwn zi?MgHl~@V33i|-tfNjJ!VVkjS*oW9o>|<;nwjVoy9mI}cC$N*)H`wpk1?(br3A>D4 z!LDL|VArsl*e&cH_7_+WHi6AxJJCvJ;1tfoMYtH3;|g4ZYjGoP!V~aB+=kn67w*RWcmR*! zDR>pUDqa(>h1bRF;f?Udcyqi3-Ue@rcfdR1UGZ*sI{pftg=gbA_^Wsxo{tyeMfebW zC_VxoiNB7&fse(<;gj&U@TvGTd=@?%pN}uV-@%LV<@gGG6}}o@i?72s;+ybo_;!33 z{t>c(e@I{i zNl=845D_v$PN)eDVIYh|Jdr>o5jMg}xCkHNC&EO8s7zELY7jMvIz(NfA<>9vMl>f{ z6K#n0Lmsm`^ zL#!l9h*iY<#2R8Pv4z-5Y$Fa6UlB)$qr@@dIB|kFNqkM5B2E)O6TcG|i0j0k#0}za z;y$S+HKdl*k$TcV8c7prCgVs8=_FlbfDDpV$f{&DvMyPV>`ZncyOQ0=m&xvA4>Fy6 zh0Gwc$y~A@nMW3p1IZEONOBZ8mK;YeA{UeIkj3N@aw)ltTu!ba-z8U*ACOzgZR989 zZgLN~pFBXGC4VN*k-w1V$zRFe$lu8enkZMG=qFPgJsLoUuDxd044WJ6BLaK-wNDZO}Q$wiX z)Em@j>P>1QHHn%*&7@{gi>SraCTcUah1yDOqqb8!s1K=~)Glf_^(D2B+D{#!j#A%J z-%+QjbJQ=?U)0~!ed+=AkcaUA59bj)k|*HFc?zD6r{^W|EIcdE&GYc;@appF@#^y$ z@EYd@mBNR<89<^;_c@h;2q>0;vMFF#XG_~$~(q8&O62Xf%hZtJnvWD zRo)-GYrMO>dwd07$yf2!d<|dA*YWjy1K-Gx=iB)XzL)Rgr}8WDEAwCC*XDQNcjR~C zcjkBDcjb5Ezs&E>@4@fM&*8ty@5>*+FW?X3zs4WVAI*Q0KcByVzmUI(znK3HznH&- zzm&g>zmmU}zlpz@zl;A7|8xEq{O|cc@PFk0#6QdbnSYM|3;#U-SN=u*b^aaxT>%i_ z0zx1bNCZg&o4_t`2$BU(flJ^Pcm!TSP*7P=MNmudlAw{Gv7m{dji9Zdx1f(8NARkk zuOL^@Pmm|b7xWht30@Nn7rZWbLoiV=N${3nreK!fJ;D2eHG;K*b%OPR4+I+o8wHyL z+XNpAJ`sE__(JfN;E3R;;9J3Wf@^~7fISB0Mj=BD^Z1L_85+BoGNjB9T}m5lKZdkxFC~nM4+mRpb_V zL|##fC{@%<)Lhg;)Kb(+)LPU=)K=6^lqTvV>LJP!WsCZW@QUD@7%u^`Z|%8$>%qABv8Oj){(oPKZv5z80MleIxo-^quGj z(RtA&(Phz1(Jj$!(L*sN)`|6EgV-oGiOu3TalAM|oG7-5J>rl!EUqT5F0LW2FK!_2 zD()tJS=?RRL!2&tMVuk-Db5u47UzkJ!~?}6#3RLH#AC$^#f!v?#qWrV#Y@CX#mmIY z#Vf?C#OuW$h_{Nji9ZqV7Vi=77atIx75^+gC;mlzUi_>0H}UV{3*w97tKwVYzs2_@ zl!PbYOXL!TBw6B=xFl|gN8*+EBz{Ri5|pG!s!Qrf>PnhQnn{{V(j@IAuS)t#awYvF zd6Ildf5`wzfuv9}STa&FO7f;;jO1;}WXTlC9LZeCTFE-eddUZp4U&zLO_I%$Et0L0 z4<&mfdnNlM`z6OD$0a8uXC&WCZb)uQZb@!S?nv%R?n(ZV{4KdJ1yX@jCY4L|QiIeY zwMwf-QI;sP$XqhF%p>#4Qe>&J zX0qn87P6MIR8USHlo-c{aB{<6Hg zyoWqp{)#+9-cz0_?=8=h7s&_8N61IY$H>RZ7s?mO7t7y~7t5E(m&%vPm&;ekSIO7Q zKag*gZlGg;HYheKHYqkMwkWnLwkftNb}2qp ze5N>{IH)+GIH~wv@q^-~;+EpJ;*R33;-2C!#ovniiU&$uDOAdp3Z+45RGO4YN}IBp zvbwT{vZk_@@+D<$WgTT*Wj$phWlLo%WqV}@Wp`x{WxBGrvX644a+H!*LgnkqHA(p2qL9aJ4vomAaaJym^FIjRAw0#%{vHPvv{G}Uy~4Ao54EY)n) z9MxRaJk@;FV$}-OyQ=q9YgC(6TU1+B+f>_CyH$Hs->AM-eWyCDI-~kt^@Hk1)laIk zs`IMLsw=7+s++3&st2lvYQ9>aPEaSREo!SeNo`Zx)ed#C+Nt)cBkB}&HFb4$J#~F` z19b~^OLe9?OP#ImrS7fnqs~#ks_v`KRrgm9Ru55+RF6`RRgY7TS5H+>Q?FE)s8^|1 ztKU<X4S7T5B$QmtC6(Z*@xwF%l} zty5b|`;xY{wvM*0ww|`Wwt=>xwvo1(wyn0EHci__+g00Bo2kvx=4$(C-_VZMzNsCf z9jhIu9j~3Bov59pouZwsougf(U95dqyHZ=CU8P;E-Jsp5-KX8JJ)k|PJ)}LX{Yra8 zdsKT&`?dCa?K$l)+RNH2+FRP&I;l>klj{^ZrB0<&>ohv8PNy^JtU9O8r3>l8x`?j2 zu7<9yuAMGT*Iw5_*HPC=*ICy^*Hza;m#yoo%heU>2I@xWM(SqhX6k0?X6xqY=IZ9@ z=Ia*d7V3(1D|KshYjs<6TXoxXpXhe$PU*hUeXILUcUpHw_r2~1-H*DTbie2>=`QQ8 z=x*q4>h9|v=pO1Zy+AM2C+aPFt3F9@)7$k9eX`!Ecj18o><7-x9fFxfEMFvswYq1dp+u+^~5u-&l3@S$O+VVB_}!^eib zhW&;EhNFgKhVKlg4QC9$7|t91HrzKnFg!G3MqtE^gpo8-Mxjw*R2ub0gVAEN8k3A3 zqt{s1SkGAB*udD(*vQz}*u>b>*v#0<*umJ%__8s}m~HH5%rlNQzG)m|9BUkB9B-Up zoM@b6e9Ji1ILA2GxY+oPaiy`uxXQTNxWTy5xX-xXc))njc*uCz_?7X9@u=~b@oVGv z#&gDBjF*j9j8~1fjdx5kliZ{*DNQPq+N3dQO*)g_WHu$4Y$mtKV~UtkOf^h3P3=r+ zruL=|rjDjgrp~4=rmm)LrgT#;Q?99>X`pG4X|QROi8jqL%{I+3%{9$4%{MJDEi^4M zEjBGRtun1Mtv78mZ8z;U?J<30`quQF>9pyL>3h=;rXNi|na-Ndn=YIFG~F=$ZMtu! z%sg|PIo_OLPBdH0R&$csX11FhX16(Hu57Miu5GSku4`^;Zf5Rk?qN%*O+dRj-z`V@7-2A?Ijd`tkoq4l)i+QX0 z3-g!eedhh<1LlL~L*~QgP#Kn-VuCZf@M-xV3TX;x@%?j@uHqBkuFKFXFz8+ZVS#?r_{!aYy35jyo0i zTiow)7ve6)U5dLLcO~v>+>N-Kakt{`#q;9%@zVJC_=I>{ygl9#?~YH2uM%H1zGi%_ z_`31+;ycH8iSHWUE&k>B?(se1)8k)>&xr3G-zPpVK0kg${K)uG@pL?le?5Lo{Mh&j z@o&dZj-MVsBYs}|{P+d&3*(o@FNkHjC1 zKNf#H{zUxA_;2HXj6WCuTl}T?8}T>eZzbRfL;{&WCGZkt3GxI*f;vH;;7CYLa3;7C zdpea zCe}%;n^-TgRbuPJHi>N$yCn8b?30+2_-bNaVnO1d#KDQf6GtSzp7=)M=)_5h^AhJL zE=XLMSe&>#u_SR-;=083i610xNZgjVJ#k0khlx8AKTSNAcs%h$;>pBs6TeS9oA`6$ zZ;8JrUP!!}_($Tk#G4keMPiX!WEQzaVNqIC7PUoVF(#F!+(#6u%(!-Kz$+Gme^tBAM46+QfjI_LNnP8b{nPiz`nQNJ6 znQvKOS!P*oSz%de*=*Tj*=pHl*=hO2@~P!B%YMrN%Mr^_%Q4G$mftNGEEg@8EPq&T zSngQvS{_<4E3o2LfmLV~S;ba~Rbx%E+N^e~!|JyBtzm1#TE$w`TFv^BwYIg6wSl#b zwY{~2wTrc@wTCs`nrY3l4zUik4zs>y9c~?A9cdk9rLAvR$66;?Ct4?2r&woMXItl4 z7g!fsi>;fio2^@{Tdmuy+pRmSA6h@M?zZl+er`QzJ!Cy>J!bvYdck_xdc}I(ddGU# zdOt~-q)E~z8It0Xl9Fsm&Ln?QI4P1;IjLDvtEARRX-VyqIwy5W>Ymgisb^AVQtzZb zNx4b=k_IFdBn?j*ku)-CRMHzsW0J-uO--7XG(BlX(#)i}NehxzB)yxoGN~l#{iJnC z>yvgQeVFud(w?M)Nr#dSCw-N4Jn8GCQ%Pr&eoOj2=|a-Qq(75xCEZJUXrpWro75(= z8Ei&dyv<_s*aEh&En=%`t7)rcYiMg^Yiw(78)bXLHrh7MHs1D@?QPpM+jQG(+Z@{h z+d^BhZHaA#?Ooey+k3Wkw)M76w#~NfwjH*QY#-b9+CH^?Y1?NzWIJp-W;<>>W&6f< z#`eAKtnFvpueRT8mu#19*KF5qw`{lVQoGD9w=3*QyUMP%YwTLP&Tg_>?M}PP98v%QPGtG$Ok+uqlnYcH}7v=6e6w2!jSw9m57w$HK8 zwa>H9w=b|Sv@fzRv6tA_+Sl2)+PB%a+jrad*uSxVYyZxE+J46Vz5NIKkM^JJXYJ?h zm+gPrZ`l8~-?u+-@Em+cyd%Mp=&(4fjwFZ8VRtwj$qtVr?1(t3I;uJ9I_f#DcGk?>Oc-?zrH%=(yy#?6~5%>iENP&2ioFr{lKcK{A<4 zB}l zm|T=RFnLh&;N&66Lz71&k4~PDJTZBC@{Ht}$qSPgC2vgLl)O24OY+v_ZOPk{cO-w9 zyfgWe!LC(kK!%AIpj=|t~IW;t_`m3t{tuqT{~T$x;}G#?mFZ8-t~j)N7qlTv#y_A=Ul(I z&buzSuDNcz?zk~GaN}-~TkN*FliW79-R*EEyPa;A+wJza1MW)h%I=!(TJDDKM()P$ zChj)ww(j2UKJFa%tM0z;Tz5Zro;%;&-#x%R)IH4ontQ5yntQr?hI^)amV35)j(e_q zo_mpdxqG$yJ@-cUCihPFF86Ww3HM3&*X~p9Z`|LyzjL2{>^>Gebs&2eaC}& zfJf+&dSo7zN9}QVl08n3%j5QVJYJ8_Rrd7gaFP|q;WYo6hr5uTBr*FDob(>*ghGd;6BvpsV>3q0?5mU%XL zwt9AWc6mPW?Dc%^+2=Xv`O0(5bJFvT=d|Ys&pFR;o?D*Vo;#kqo_n6ZJb!y-Ub$D{ zReDukwO8ZSdX3(AuhpC6P4;@c0dI;o)mzD1+grz5*W1wB)Z5bA%G=)C+1th2-J9v{ z?d{{u_0rza-Z#DDy%W4|dnbFRduMp(c;|W-dKY<@c$a$L^{(`;@vil5@^1ES_wM$7 z?%nS_>^Q4eO-M$d|AG1UoYQC-zXpLgTB{&Z}>+0-t>*}jrEQ5jrUFP zP4rFjz2$q`H`zDWH_tcUx4^f|x5l^Dx6ZfT_knMNZ=-LQ?<3#GzJ0#^z5~94zOQ|! zeBb#l`Y!n{`>yz|`u_CY^4<2`@%`<`{XDm4tNyd^dIsc_J8F+;=k;_ z;=k(u!+*_x-T$ZmhX1DjmjAZ@j{mOzp8tM;3h)B_fI6TFXal-{K41tK1ExT7z#j+& zQUjF&l>^lSjRK7WO#)2=%>u0gtpgnb9Rpnh-2$%!@&fsR{(%93fc_P6WOQ zoC$m%_#yCf;9TIBz{S9&z}>*Tz+ZvC1NQ?D0uO^&5Cric5hR16pg5=wYJ%EeI2Z}0 z1XF{Rf|Y|+f>ndng4KgHf;EG+g7t$9f=z>I!S=xp!H&UB!Op>+!OUP*Fgw^g*f*FP zEC?0`Uki>3(!tTeH-qDY6M}CCrv;}67X_CFR|Yo*Hw8Bbw*{4V%Y z@VDTl;N{@8;LYIO;Jx635FR2zWQYn0L#mJ=lo+ywoFQ*07z%|_L(M|XLoGrrL#;xs zLv2EBL+wIop-!P5q4ZF8s8=X2lph)#8WMt`v7xs^(?ZijvqN)23qtRNibKmoJ3=3Z zc7}F^J_>yt`XsbFv?sJT^hM}!=tSsb==;zQpcXG>kNgG>$Zh zw1}idx6mv>qiY>*S z;!1fbrFKf4l)5SPQtGEPNNJeTD5Y^q^OSZeX(?S&x~B9@$xO*g$xZ2(GALzu${Q(T zQzoWNPMMxEBV|s?nv}IE>r&RIe2}ssWn;>wl+7tyQg)>5PWd9`%akK2M^lcae3x=M zMN-ksXbHkQu9;$rw&LhNF96zjxM7w0)k2l(SK}m`Fgq3~!OU137LO%hiI@emVo8{drf43`rvJeU{rVSZXh%b{d7l&pc0kD=rTDESde&O*u0baixf^$M~x`u5My$tx;h#k2Sy=VvVrISQA=7D`^$2 zrZu#d*3o*}KpSZjZKmVs_%&EFtU1;KYl*eOT4QanwpcqX4Qr2ez&c``=mfeAfzdptD9|*oD7&B+f}`HR zoZPJJg1|p-AkevKy>x~DA4UH4i8k52GYSV5rsWST$jq*fs!mr_`N!w~OGFy#Frvn6J1{4+Z;Sl=zR@>h64Djb%eu~3+qKHi zYm}3loi-Fv+V3e1$ySllrXZim97!A4pF#HDxA2e8q$|SZyXX3CIy}DNs+sxy0vY|$ zs0m~h1zP45X0lDjHcnxOrUB*}o3>_ujSic~Ma%5B7Wus&f6^Dduo!;->IVj&cKNxv z+{d}0(+7JM3lw8HbYd~qmrkOqAH(vHPRz&pV*{`PMl1G2gSs2~S&*HJl)#{D8l$bW zC0)_67rN-`!CB^pJLqKExg2{PdjlJd(byQ;Mc1I~(N4NPGhmZZ zTSeQcO+ogcob18O2#CFmzR#-2bVXv*dQFD*EXc`9D=HY6Sv0U9yCeGa;|oWia%u~) z-ZQ(PX%^C0IlXdF%cLum(Z3-Dia;BbgLFZh`X7$v1wRfDK;6K zf=#8}w1@UC#inC3u$i=v_S4nq>OGp)i(P11W=1a342nl@Aa$A3KO4zSc=Q&dwb4)r zheAkYGs?7Uetth&?LRQ~zoV=fT!1Yq#um~6x+-@O?_f(Y-4d)ATS5ov&=PDJwww;r z5xPnT)-ZO@%+KqU(|ce+%rdG4iUvn^2C@g4*&SGJ(iPSi&h;9guF1@<`{)CKmKm9W1{no?qo{1bw!Yjd ztw9blJNbDT1w)r$Td<+gKW)c$Ac7e?gWlba4Yk$&io0V5vR&9m=?ZnLw3Y*lGJ57_ zKdxda`V*>zyY^48PnpixjqSnq(lzN?^h-;z&#=$2FX-BI9l9<~c;_8vL`MCTqu8U8`6#F#&i?9=?X;A&)7Na7wkOtD`Ke` z-JEVgx1w9q)w?oGG|I?CHltg8gh+Nl8^(P=Eri-T+6VPA3OeQ#=AgDhcgzfs?5y_r z{aa)Y%Fc~p-vD7}kB-Zx4cg~Fy2&W(ZSo6qm|kj`(H~X7{IPB>l7pO!?8m~pzvfSg z1R|AumT;xW2tgFi>kOQK(kEomj&}n*~D+6>YM=K}RgG zR?!8!k3GO10t^6v0|JnM0zAM60w4q;AO;d31u`H93ZMikpavSC1v;Py24DmxU!K?sCF1f+mePzh89RX|lx4O9m;Kuu5! zyaZ~4I-oA72kL_cpdn}k8iOXFDQE_ogBGAAXa!n>HlQtN2hu=$(1C7Cr_mkgPIMQ# z8{M5wr!(kGI-BlI=g@uWesn%PfG(s5(u3)t^lS78dK3-mH|RI%vGjO)BK;OUnVw2d zr)Sc$>ACcLdLg}-E~b~#%jtLN5_&cLKE0M+Pj8?%(Oc+k^bUF_{So~My@&pk{+#}j z-cKK-57S5JWAq97Yx*1dJNgX$1N{^IGyMzwEB!ltk-kh{rLWO{(l_bb^j-Qd`ab;- z0)W~XbON107tj@S122Q_pa)0?uYe5D6J&xckPUi)-k=Z20k49-AQ$ulc_1J32LnI> zCgfZ%oT1{e+A1Y^KhFb<3d6Tn0;3A_c~29v=Q zFcnM#)4>cd6U+j$!5lCb%meem0rpcpIxOTjX*9IOEEf|Z~ItOBdSd*FSr z2CRjEfWQnv0D^iDbb{bj2xtgqLa+*gk03Y(!EX@!4RHm;?GUd9@#YZk0r3KekAe6+ zh_8Y8ClEgY@e2@t00|`|?2xDeiDr;^84~>=@dhMjL1Gmoc0uARNSuSjZAgkCnFz@+ zBpX7q3ncqOas(u&LUK7Iw?XnCB!7hDpOE51$_%Lpq#8h~6Que<3PNfoq)H&Q15$?| z^&_ONLmmZr2FUY6UVX^x0C{~NZy4mg1$j#$Z!_fWhrI70?+?hwAzusmZpg0%`K=*8 z3-Sj;{shQh2>ELv|C4{%ez1|X^X<|VohxeR8xBE{0h6d(7(`|>C$IOTHv)x&b9xm$ z;c0+vthDy&idN;57WE{e=XTkJtcP3}Y&Zz%t(N(DOmI_L#x7Py$8<%r^2sRexgdFr z+rs+ErR(3r*55f@(XxE?KY0(GvU>*6@lPvJTErKuh_3012LHQ=vM>H1Tl351?trH^ z4s-oX3o$=SU;R;5MvrvGJnrg|QP0iEWc`Q2VAS3tMJR;VWngUIY;=jQj%E(o?k z&S$Uuf_{ZTWQ|&B{-F3*tg z6DtA5ecj3@p>%(?%+4FwGov6F`}tpJo@WL2N>{Y|KN9$i8@tHL>GK?*BLB2kc0o3B zH4B4Hkq=uM)IV4mucj-~Dta%EbrM3n0h-b1jeMNaf^M>cP|V$?qJpB4Z7}-d8BKPN zm4aq($|>bZ+FE4~c0@vr3-Sl{4+qPMD&~>RM#?yUAoBc63o)=lhNUaIR8+{5E%wCgr&^g2KlNcs*UwuzUha6OQJ#g6JsSN@2F@(a&K7VpffFhMum`@XD;5G3A!? zWE=fMqoF@A2*jqJ{_U3HHCQ?0o}<_Qp`V!!f5sivVI@td&>h8ky)kF1%ete6tei>Z zc7mU5xt3_8Fy38R^*3YdfBQKU+Y=h6RT|RQ+1aHnG~SvOGbLS7zkCcoc^l~UGksLN zJzMd#a`!{&!4a!II>eh~L(iKh1*GkX4nWt;2 zOt$(t>52~JtNzJOcw!WCW4$b_`mmzrJ%>leS^mO4!JY-#gPZ0xMzdSJ3jS^W`>}!+ zRLC>`m-cCih={%wSdw+6PRT{0RYZQEzhXh#x%bus1*hQcJa4E;IVpcqdOBsvw%Fyi-Ss5$S6`jgA zPD-~G=O6#~ObR}Q6}GC}?e>p;e>9WwUlTU?OjgW$<+dZG@2SiP8K1}2zvekC@8dQr zb6N;r%t~7K9KG{|%NnekiNZ=WMV^z3mcUDEQDwPi+L23pxIeJ5*JF`J)b9WZ7n8MV($_Amp8jWbKj+Q7=%nyyH%=m2`M zi=KF0mdV-53f=x3fgq=+%d$5+St%d>A4oxljg4ySKP9N$%}Uu-?$P=WrNA14vd7Tp zZ2ccU$7tnzONN57dgTBsX?KOp+7rM%%i%x5R=>C0=Km>!Cu((=)C)9lO0#^DmGD`) zZ=kdUCi;42_2048e^Kty|71`9EA}d@8-8TP>?`-^e^Sg7u3xx3Av2jD6z`Fy! zrl3Vm&jOUi5NuR{5?=;035HD1GnrMrxOajbqYuC-M7g+4vNKRVNnx;6TC^PlPflhM z0`?xheU50B(+OpIYlM`QbGkxW=U+WihSnieteEf1tqDqZf2@(8HhD$p+1h`6ju?|O zVr9qvL>w#VY`UU0M^^b)f1WkBefx z%DM3zw*CohpFX`qv|?r4dJb1OCgbrM!PBE6B8`=FCtcC#e+T$K%sSDTt^3|{Xp{dz zt#@aI{rwzsp|K__OOy0ug*^B_z&IAxmBy<#BLV`fLbK9kt*sKd(VFpcH&HqC33vT$ zrW}z^3`JWJi2lR?qJStQiim;4AYw2v1OgHQ3IZMkdgMM1PbYl&**?{l`A}gInh0 z<@94x1+7p0Gn3L>KOa5*55-w1Mfa(nX__}Eny`rS5=+;Tn=v$hVA10RhjfLlbS;@o ztjNxV1oC_JLfP+6tEupbPcd1b&$^|$1B?3PGdaPf@0i&;&?rAQ3nfaiIgiBKDCd!w z41tWU8hv9LwrCkaNB^Owee^$FRl#LE67z@!n68+Z4}r3nSO|fN*{g!KedHEpM4P?E zKkqq~DM=I)%TRtUv4mI(ff@qM5@I>A0s<`rI=V_X=9Ze~Wn~Y^F6@yN+w0OIJFj<9 zpXimXW>Zj=;1AnJe?)UIxq87-l7fb_iplFg7qW9)wc@*4)oZy`wLfIRa|Ah}LFN1SJH`~?D6G4U$|?sDRIk+{NO zbBS02fd>(}gt&^0hQNz*_pAJiKqcOflXjE16NT+I3!8rlHk!Cf*JH~4yA)UC0V!Z8 zdq`p=AaRl)Ns=OYB+_+32tp8qA&5Yb0zoPSl_01LL6s6x7}a~EG^+PVB?MJDy;tM0 z-mCKhvkG8F#v{x~G`g$BFe9x9Gct*wnFE6AtlneJNbl)l{Ybh=F9MB3tkf(feGt?t zA82HVOkwpNiFz67y_XO&WF-cf+NF?D;KKTO!cN24q9B z5!sk*LN+Cvka4>H&MLxLPlmHh2+*bi){2q67|wc=eV7A+RuCY2!JH9i28E65$b51DLt1|b+7^=q z5VR{NX@kh2QPPl4g-AbDrDme{;&Jc8gpeqF3Ab1&q?hy2VARU5NO2`>8(&ofe+5!kNIMPrXajsmS z7pPSPwUrENB@p!FPEf|Dz9ko=m#>=1dF{E9q69wm>F$H^1qNeKEv zkPAUS2=XAvhX9R~0T7^(QdmNsidoLnby-2v(y} zIIGcKL(otZ1I_SK&?se%ZFSuL2n{GPC1aVRq%3oz$|xSYQc6Q5Am%77rK9wefihAi z%1p&kC>nrhmk3n5rkLS;v-D3ufS*U*M7u$Z%=OCR}bD_@XS5z>Y- zqz!`rZFXh-HEIMy+DK{?b3jlG!IJ11k!Di(xsDt|jblhd>R?$hH6DWHORYqE z{J?4m-h<$M2-ZMmr{X#Y)I!ug0(7sR zK(HHvJrL}L0No>U1V4x1ixTQu%zWOAk#-k?FFEsh;4x`OUXWG+(s&dijmLvvUyL-K z5Rt|cQJ*pg1p8Uim@^^`ZBAq->v>8ZdSX#APX)ojVx9(qL*?U)XW*Gx&Uhx4v%_dI zmWO;NG|Br_DbSSikPr!VqRAWel90$J$M;W*j`~_JI7Fi zye9xEc7H%{t%Nr`1{)oN4FwL@IoNJKhV9-9*eU|s6b81b5d6u(HiLm} zCP6a?1UJ}8T;_~mQ*-^efVYT24f)cyig}A6xLr=vmhx6aQCrTUc86hRC5zhKQm85J zaMIrAt&5U|Tr1?N{Z&>euFPiM#|&v(cw2efc-wh9cpvh1@^aU@;?aU@v> zaXrKh5I2_ac~R2%q9|#68N^K-Y4MLpLr?j7u^x}MH2iPNpL`P{jcdeEf+v=bG`^o7Ldfs~Xc`x{AlR1h!^Cok zTM=xfNh3by#8u%}XG!B%V@b0i()eK(P;04TT$wujW{5O?U4A`&eSQOeLw+NEV}28U zQ;0hto(yqx?JkI;Yxh9h3vnOB{U!Y7(fE_!I!0O=!~?PT6OTM1t;!41DxlN&=?rPF zKs?BimdTKo#m{CAh=(8^j-C-|azz~1k-7XlhP8eWPbuc-Lp-&dtQGPHF{~9atW{!J z8;q6=&?f7rEVk>naneTc=_qQWSk$Vb_>(^v1+A#uGZx$VWB5}T(#G<~@yGKg@F(&o z@!#UV&7TbM>JYC1@tP2?1@V_4UK`?dAYK>Z^-B0tW2DWDkv13N^*PcSJ|eB@3(_h= z+H!`p6%cR0kye68dwPx$*YE52A25`yhj^o6{sxFQE+=JM_}dxEwlb78VJLfcN(U$E zWB#5fVrXIl+0AAMvH!^D;D5&_^$2aF=?_AEsvkP7sOGJ#AW7bpZufl8njXargTa>ddijudwW#Ct+K6XIDAM+&_+LHxB6LH8JH88OrlgTp!0kh#{!Le9}IP^$=P0~plM10Y9ms0~D@2?h}~ zb3l9~8wfCGgqoD=#}R^23~D1GP8SQ%r(iiz8!Z?cMGY-!Bh+3;+DR~;(N1raB26)# z6ZW=XY8137ENE|*QHU!tTTsk!Hb*d5Fi$XFut2a-ut>02@D9YsLVO&=$3uJq#3w== zMbvLW{B4L&E)gt=ake7H*(!*hKM+j-$EQE$Y|abLD#F=jhO;dYpUQEzo#AW;;tU-S zpT=^=oDpXdt{-;`_A;F9f%uGK!KV;CsG(d5;DRp&2cn$qXE~e2=%z!gN}F98w2wGx z#{}%k)p`M%(nlI?Zds+cGN%RS8Pd)Oz8Cx;_)+ka;H=F~pHAUs@vgHAdRS7-?4_zKkR7-N&T8_ky&FkoFft8hXg>a*nizh%_Na(98kx z6)b7Y8Ii_)>w=Ik6e7}u0*J3H7K$KVQa;jzGNFCQK6Agm$4rm@IS(T|&1I&10;E_&SKA80G_rZ-Dql zh;M>8@(#9?2z^n~grR6KAWVh$R*tmokAi`ZUVv5s(1djmXhIa%Z;OE@Y=A&3Gu{+7 z7q(8F5g!8vM`;s zoWdR~W*;NVDeTCY+g+tfag=2X^BKx|3406s2y=w53i}Fkh5dwi5Z?`Pq=)xH9O>cD zApSYTzkv9c5Z_lK>>s17C`K9b-u82p9ePCBu@{t8gtE~LWp6_K07uz4L>VG9%kj?m6BAm;rvm*>K3m9UKmLf)} z-o;5P7P9-T)(e-ioExCZ(k@`9b@vk9%3gX{D z{9A~B2XQomaR%bwmk2jSXU~M&Vw~-S_z&Fd+0TzS`|Sm172)hlhO>PTM=R!RMw;*- zV>S;7F?1Y(_)m=GWX@+1XDWq;>&TPBQw(XS%gz-GQJ4KvPSVZ@*^Hkh!XH@D&NIxM zWk~zAG-*^fPTH@+3sH@R*20mC_InwnxFUZD?=hrZ6J8hoDZC-PDZC}TExaSV3-OB( zzXb8i5WfO(T~tF< zQ&daz62u=u0)qsA1P%!T5+o!jNbn%RFA>#=k|t^pjRizaAbQYAH0mTok75Br{sOg% zpw^y2tpg;49BQ2rYERGH;CeA#gi?KqMXx|YTrBDd2}wCY>m|xzh*=`)!+=Iek!lk4 zMGB3OmEuhCJ14Bas4$9I0fQN#D5DTpWT@y3hO%Lz*F?ibBSa%bqeQd_ie86=3KB@L z1`=9G=pdnogaHz$R#S;+bkuT+#>Mp6BuJQJmXmn2mQK7_OOJlp#{agKE}FwYHW#8t z;Y2N`2z~oh*>Qkqsc1O^*)m8Z6pL0sqMR$~qE({zqmZFgYSh;jhL^PrWTjWcm2o>b zWHySnL@7hLzK91~8Kt-)J4K%}lGtNiD80CAmN6D z2NGUL_#ojg5q%NUWd~xEp>K!@aJnqSSxxjfnHL!w%vZYnkCdHeC_4iQZXI3pBckl- z85>+D{wn&Nq3kzEgo{NNAQ362D!U@OhIkQOMbRdafM-D73MKrBX_iE%L@CdHJPC+3RvO z28rsBr~!$Zkf;TTmmpCa5_L+%lBhNlE25lCPqr2L9sXhiH7ClOdJtcVzrqVk%hEbBczwaRTyoCmf`=!i;_s> zkf|xI&0;2giN&mG8Kt-)4aKb)${L9qi<^j>ikpd>i(80Wid#XVIV4&@q9r8I>(-EH z1BtefXa|Y35^b%sQHj>ruoYi&(dE6d5N*UvgO@9xt9Co+zFq zeoOqec(Qnkcq$~iL!t*H(jkFd$_z;KghVDJvLKONBAy;KnBv({=U+S@61_Nsne*8B z&wIgGMHqXRVQeKNdUK4SC;KcDzemu_0SV-%%cEx$XDT>Vu|d3vp=={0UM&`HhD6_T zQnp>pY*iOCTh)nN#%79lF*dW`Q*9<#%8A=6j_y?#f5wuQk8GxR7i%-o^8LSbAXny~ znAxl@J|sRY{z`mAd{lf)d|Z4&d=e4^Ab|!(AtZ_*F%S}iATb!C$6gUbOT?#Q+U#@; zwI3ldjMHYrAEO3epjHvon9b_q%aC}DLyg(2UglDO__p{i1KJ%(j3^f0gT%;kg7!cH zSfeSySartiG?x&J(WFZOqbQ6aBN0f%tU{BZDFqY(FbnU`D#R60O3a8diAtiDXe3&R zPNJ6>Bu0q|5~CsUCM3o{Vk{)aL1H{4CO~2$Bqo(e;-U&oVu?~Fu|wi5PN7YHOxcVV zlvRK-3CaR0mV_bkc8oGf>N6D@*NZhIwGd?zUj`70*+V!(Ieo9MUYrrB6%f-Syl|QK9G2a!wjuK#8QHY7kkqyGM^zSVlYGI zqnN{N2*OMNU~V+j-*(!M6whT zt0D0oB;JR_8c3{##5zc%e*@;l2MoB(m4(1sM1e&s9&Iq+fTIN#;@|lVyXfA4NvE&O#Y%3>f2PB81sG(FK zq|>%D+UW?R({_~BX)^8$xg{qh-$Y46`+E^-JIg4=f%b#scLuZ{B|k~dN`97{ll&q% zFZosS8zer0#K(~M1QNR;diW!;7ZRUB0^P{xC6WtK2TgJ%8g5FiL*fh0LEHBz+&uJx zvx;!`fZ+_S!h9K1X;K_<_VmZ2#X3d@Sc+z%_7_VfkT_62%A^V@+Rwg3s$>EI zv@(yLS@jx9)j$tME1jyri84y#Sj41e7O}$!v1dI^jVqEQ^&!NhHmP0ekS0r=QkT>% z^+?fF>=8&Dg~TyP9EZdSNT8_TYe<}e#5W~Ue^i%A!%M9miNh#F(@ZK{E#=PP1l{IU`-hJ$zBxQi?pLVkw$^`o36-W}kj2CuQxW zofyhGFqHksP$un+C?kG)3S~+?H+3fMAw_FjXogn$3JcoL2sCMDMg#s-N&|AB^_C7` zKGPGfxGnzMFfL0OE#xS6v*y}0>+5`kznZc%Xs&qPo*)&L8E0)fH#PxDwHb*+2 z0cMGG9&0lHWPn-70CS@hFiK$Lm{}r4t6L0a%UH~Al~IZ-vRb-{!R$Th`_eViwbFIc z_0kWd8>DC&1_j7>A#o29e?j7JNZg0S14ulCBvvBb9MfmpW0>uNB#7xVl6-_2DSUxh zMKIgPV74EUIEUFGMxPxfuQLZE3FZNO>>25^>Rdmblrrf+(yt*&6-&Q?B(I#HosmY< zfuw9Y5XndWy!0#+29Sc%r0KcYI_a;{Xg-jX%?BbyWfkKt@ee7J5G1`Oy)OMzdP90s zdP{m+dPjN}k`hQtAt{5T9Fhu%o`g)QAgP9=rbPNzOrt%NVKRW7lM#^A#xxqKhol*j zap<`RWc&-%Du9}d$q1667T3j4lQ9`Vyf)~;LFhmaabX`E#GL7>v0jv!WXNYKmZ63> z6wBfvX)GUTGONtaYBZUR(P*Rz>85Ax^tIJNU#r6Wryw|~K3Oy^NXDiGkqKp#=89C3 zFarTLnzCB5mmq0@q!p4$khDS44oL?jlOgGZq^m?$CyJXamK7vx z0!cTAoA7| z^p_L2Ub1Lbkc`a=A_E8*K?7t!@zQ(iIAHQ+1+4Xyp$E+xAsH%1ks-3z8ODanhRI%& z4VR6Ojg*a&(J~0plfcOoNTx!v5+o}_vI-=tLb4hptCz^$h+0qC*l55hn+VAoob`N( z3pmO8FA%E;VzU{<=0LJ0huD0C7};C4kU5wqag(*8XJkB`T+c6+FlC4I;09ls_24ri9<&doR)U_v^TYHjiltt5mWNcax*#H?&*&5d7J~LF6 z?UXTjL9$)4k7OUqK9TK~?UC)3eJcA5l8qqQ7?Ma)HHBm|NFrm{0+KBu+3NqX_a1;z z6&y z3-*cyd)LR_{%3AUAt5YzeV*t2-Y>$vF1vT`ojdcJbIzPOGm{u3#{~^~RUF$%7EIAK+A5o(f)IJ@AhEsgd zXP_>N5BdVsxNdtg;k1Lk8T36t?OTG{G!eBQu-~c1StZ@gw1F=vPy2PyACgG>T@-0E zP^1m|0i__OJHQ~PcA!>+plMUIYAvOuwTzb4a#~(1fO;0FXM=hUsON(Ecu-e>8l`e2 zsOKfLhe;w$tCv92qWM^*fEMcjt+pSuK7gjhtt;Z%0H~{F(6ng?TF>JGa>Z+hXfqHq z?NCtH#I?gfJwG|jv^m;50!*8hEa3v`1qe*aW(0<8;M4P{xb{e`6c(fv!-CWclSopm zC1F9@vD$Ik@!AsYG1>{*Qtd=73gQ+#r znYJ3#r-2#;=^9X(DJ)1Uh6SlFK+v>g3kytlAo;gjOQM3b&uO36zMy?kyGQ$y_GRrW z+E)QLOHp48>PtXHP8mMnkP`j-IwY&RK z>jP@KEJRI*o&8&7)O5Lsnl6u?Ob$?QCyODAXGD#cQPYjkp~)22p)2b4xNanaAFA4}-wN!~MEjc&effoh*_ zA*df$OthV#ehSo26KCx+{iyW?wPggg<)Gf7pmw6DK6`Q2>OhAZf5mmHLH$HrhuZJS zBtcuNJBNUF76EM+0gXA}VvfO)VbNEs(t*O;#k$KR-Yyk+dlr@Gfn2>xl52FE32xWw zuG3wwTd#}j+H@Oq8+8cxbD(}6)abc*5!8D?{Sv5O2K6hTel?-nB1^WdvShmj)UPR$ z?adC!_HI9JeZlR1f*UsT*A?7wKZ}jJN2EWXexv;_N;bDrk5B5JBEane^;>b>)1ZDk zN#LH-y-1L0)4hPSf%+Xp=0G!2lt;a$dsCte7yq||dT$a*-qU?fD0^S`f$l@yKHW#U zk9D8uKGmT!=6z6q0O}7xy${qMf%;=me*)@HLH$`m_k~Q^Hs6rsLWWGAf{^t(q^{@nXgJ07=#csD?k_-}jPANs_A1K+5!K`j9@XkLc6&QT<^35dBb4 z{|nSVg8C;={|xG1K#iv6Z=gm~^N)mnm_(UAN0McF95DD(ri@ax%QD;9f%-26vvG)-uuWe=4l)--jWKHEjIzw5)Z=75noV*26rcvg^;3Zwm?UV^^)n^V zaJLI1P$>i%Ts;&hb$8Hg$_^R&6ZBOQX!8hY6x~ZIC4;s4W&+wm{UUvxezCq@-=J^Q zFVQyv#RA0v#RDY(r2*jk5Q1 z)(3H>$0dT|`m=yCD4eZB&h+P|w2}iTlss4oP$WMWRWu~A!a?{%+{SVtFoSlev|$NiL)&tXJj1yK&g}r-mJfeaCVFS zR{eJUZTj2wcj)ib-=)7BC>P+iiIfK@FHk<9{6GbO3Idgy(BCU__MrYD{lm!Fqd=u8 zoTUSm0n{)8T4q0JeE|*E2#V{U14`LNUH>8hZIAvXascj5NkybHg0@gMOsUB?^=}i@ z-U2Eb*S`Z4ZfTwrYVYg!NvM4&qBaD3kou2F50b+1`2EHO^r@x6krBC1P@+8fEB&_; zcHfBDW%YIkCCyI;72)n@{V)1o^}p$V*Z-maQ~#I#Z=iAjcZ;NQfyx6aAE*MrT_UN& zfjS~#7$EgQ4U}ZA8Bh)$DfdCC_R)1}bU$`|z|LSs>6b(nm4JaCt99uVp4N(y}L%N6@*&Y2L%eEUb4LKrXhHR0sF-asT zG>k#S42K(zFdS(ZVK~Zgv|*%SlmUfkF;HWH8VA&Pph|!`1}KzPr9e$g7>Xp(W*9Fc zhTr0b!{iT8?Hj67{Tr(HWfGJDLxSRlnLtfe5SxRD=^jaGB?swq65lO3cOX_}h!Mo9 zfjTyBr~ztfa#GE((6CrSjLaJbstje4p+S^tI4ZxtRAXvnv1Dj5ESE4_CSo?dw`5A1 zlMQDQ&Q39$YG^fpVYT5j!|8@KhBJVg0TjONETCosH3z73~Oakw$5;_ z;XKto!v#Po+o@Cdvb8`hB*-o5mt}pCWw=;S+;A;W%6968^$40Ft`3j`$R53@P{@Vd%}3E>xP#bg3%ZjQ`YAZlFYC|E z%7gDWJS0K)pa@-EFE>z<>@Yk>nA>T1!tkVFm*FYH(}rgZ&l+|ERS#4HP>nz>0SbEy z%|NvPwG^mj3B&WUYn*q4Brvvz6I)}xZ!)CaAWjjj5fnh2At?lnEOR!?qnjTFb)WfHk|Ul zzj)JZksoJN8B;{ki~~i|T6;^Tq~VN4M9s(>1*67zm~oI%Yt$L_Mgvf*fjSMS(}7w8 z6iT}@fm#c=fiiV=!f29EGukB7jM$ktM?vkp4%GU$RPT!(HAWCMV>(dlWYmnfx5Y-| zP|d^S0P0+v+bNw9wLGOBhZ`~cCvHT;`uw;N4eKN~R5u=BJW52(I6_42LS)7`Qbg^d z9#DH*d0eq^yoA~~5w%NtOQximWSl`zn{1q7Jk~hXSY|9YPBTt79tYHAKwS>h6+m4H z)Kx%T4b(M2p@6?GVVo&xQsZ37Vl!3(rEIBAwJAPaYD>RR>w{1;E+(X*N>R2{H{#Y7 z7}afTCI^Yb8XOI+?RJnX}D6-L7;#?`-Gn-hR&d!r5(vv)h5XLy>5> zwMFk^1;z)B4-?8B0_v`~@e!czPLi@6MiK^O+==6#)IA7Vn~;yeL%2Lz_h?&%m)*t} zB*dN<5hIh_4>E#feAW0KLF_f->&7>XZyMh+zHNNR_^xp;P!9n0AW)cXl+>7Q^qoBh z)Z;+yNEqLj5&KBinx6r+Q$g&>4z2lYKVyAi>_@`bPe47PF!n1lrv5&ql^kT^9rixO zb9?X8q%vXrPuw&Bs9kYW3Q$ia$C!yR@uDO%aiS!98i6rsh$MTanu{U&CUFpJ zy9u4hD9CpAl1K*AxymGF|WhU%hz9Ca)8bLH>k2439S}Zb+ zC6u98>aDm5y;4aIteYm7CP|b{6e%ME>j#+uU@A9}DefuTP18lj$iVu+lFT*DCyX6$ zsxX~ksx-|rRhgrIc8~}m(|Xg51hKfO&9uR^(X`35*|f!Ug9$w` zKLGVFpne1j<@V1&{Q}glK>Y^P?+MdZS&ZExi!rnw{!ql&U+v10PU&Z?FN|S8P~3#( z$)AcCdmI_V_@F#;h~YuorE`a}eARwulFIT$)60?=dx?lKdI0tm zO|Oy;CXJ)=`};C%X$og=nckH|**kvNP0L{`5S|30&V^C1stOi;q zgJxzBG<}KwVRDez4QiNlZU@ag$gD%q%vzugakCz1V{)LG&1Rbjni=PMAZR8e#_SM5 z>mkHeoi9UU_L^~&3w5U1FM?+6Et!%gV$Md;%<1N+d9Znid8j$VJj|SF&H@@ybpY)I z+6A;5Xb;d{pnX956XqNVG;_WLn)wKz0}5!N4$ubogVq<&Ff1r;9uIU-0c`?;W-c{P zBnQx`K&MG(bY)m|SxQZoo2L`lrU4y}n~wuJk|b=i&Bsfy%@tuwC)AuE!WQi=)%ZQi z<6`Co5^VED*vM%70h1|d>dh+%Yz^i{^AdBDx!K%eUTR)uUJi5y(8GYv1RBB12091m z;XvmCotH4LlwmvBe2V#0)jl%-ov*-lIM7D}JrW0?=u!Q!^#!(b32f&9U7)~rA%X28 zs(>6o7m~@t;u&FkMybau&A2d7+DF`M5D|4q3a8DFB9lq z0eX@G-RlS)n~mGS;z5R=(7_>|J5=dj^ZNw3_kf-fH-7;1u}LELu^D&4Kv%8#QxUnT zD5kXH65HwnPNp+|V4AX{=@vI`7iU|7L{cH(9?lN zX*>hynLy71dN$B=fSwEV@d-Bd2tIW*{b9qv!q*wATX9Fc0TE90lJB}V=P4$6k@eNF9doK&~-pB2D%>T2A~^(UXrkklSG+if=t_nV>KsFz@>?WM;uAfg+n)c!XX5*%dt7U*l@mhXYS zHc8livXI~)%g+QhTyOwk`;F+$>wD6h>;=J*CaE_dKh`?HsurQMrijqB5e51iQJ~i! zh&d~7H6e3W!K$$yW*ubJT6I>v)nG*@%SND)^UXkS0s01@6F_6z*$VWwgw-s`HmhBd zZC3P#+@#31TiRvY9sS7l0Xb_rB4>>PeY1?5btodoy~vx%0Ruk(vL7rtw<}QVa4QKA zvZ8z7*0?nv=r9!m zxz^*Y6{>yKN}wN6IC~7}CxPBYWZP5yp!Eeb5+P(oyZBKBG!h}C{*LjI0|qREfiCIX z0on@di3GHjKtCS0qVcmMNzhKUt|o%1%?c>gfZmCM$$B~wOiy&@%yvs~t)un;Sw`UKIW7#d-0vpz*M>03Q$Qr%nyndhy0B+6bC zDI>%3)~5)jZ*{{|N%Fe&147vw);FzhS>Lw4V|~}U*ZQ9IeW3ROjm{bT@Bz?hLF@zi zBcMM9`jdq9Lz%KqWc~RC(4Q)lecrA=zwU>uFOdCAAo~UA&lJdhN632Z8`uWg&~A#` zQh@#oK0LUsLh6}1)*5`>frX4&0sT&h}ldcVr0JiK}i*2=q@t{|q#~`mYIFNJ7jOl?0hB1L)rr#Qta( zWQ?kxu|6yn{6TyWPcMu#u-tN4cyv;Ad_X1ZJKR{#Mp6!F=hZV#u-tJVWRy<<&`AI z+ZGVUDr_g%DsA&@Rkmtd%vNKY4@?R$YG5c}XkZv%SYS9{cwmHttyX4iu_VT9OMubH zj4@h8j4{T3#QK8R$po=efH_P-3=lEfYHBArfEh%*wc;6jo=Rke?JOIv5EQqa4U8^s zTL+9jNysj+;f5G!pV=-Vf{ZaBG1Ns!%z*B@jw!@kX}d;(>}nA*QxZwqY}*KA8*CeG zn{1nHTWmMj61E#{TY<3vV+Fg|bHpWsd>lQz+YslnL8xPm+TyzQN$$*W`?p)hkuM+x9%6>^We9aoY>Pq$Ww( z%eL2uD0>A(8IwjtneBBHWlX3CQKk=ktvu~r8xC}#C(ZVr2wDU|v%QXNV!8uKvrlZ_ z5zs!heP;XI_J!?B+gG-)ZQt0w1ttp2U|@y-GZdH%V1@yc2}~9+*$LbCGH5@^((E^2 zaum?=+NIeM{halIGdqo(*-?EAmpQZZ$eCTxJWLK?aOQb% zKW;YzQ;-~IcDo%n!)UWR2xmB6Z)~%>(PhgV-lNMlMHxxA2kjvdG&{11a_C5OYuMey z8^RoZAkyqZ?0HCfhh+tFZ(+m8e0n7Dl= zFcXplZLa+ULQI>zLR6cjD4GrulWniDi#uR!w=WPOo0LS72K!3FSfhQ3y~*BeZ?P}6 zFS9SVuK;EWFvkKj6__$$%7K{%%yeMzEoLO_C(4YSVn3ChtlDQ^4a`i1u{pq0;z%#L z&X{@qjP-@F^9W<-12aou>>?u0aOoy;05h8`x*?uXoCOqdc9k71rnvoTVCKf{*8+2V zl9a{m8zss%h?G?jxrBWSluIXclS_JUV{oM8JX0yp-DZ~}gzRF35L4A#dL_-Bb`m0F zzsr8N{T}{^zSmA-gzWDDvm|c+0GOsEiTl_t#R%EO z7$K$^g_QjZVsf=~2X4SRg_&>dKS=uXdr`D4>m`+v)+gVJp!Fed_Y5-_WPIT;viSEmBgnsBHk(dJ+!%p4kEKoM=HcVM=*AG1DS=CC1V z4m5vO%a}P_h?&Ek(n=0sP9v@j@rla!M;X#8^l4)b8!9msB*-2VA-fq3Gu)UC4Z8tHcVkmYv%^7_4|42uJmGlK zvCHw4<7vk;j%OXafw>i!?ZDgy%;vXL1v0XF5L3;>$N>X0MOjA99kT3e2QIr9cYFiP198W9z&w~F zWIsB7A&~t(l}B7%-0mvjdo&z&ruWlfa;f{}eD!C!7WeF{ecmWKQ(rKBFMEyF-xe>1V7D zj5$Ndm=o=)XJy8mQDm&wfpce;6PI0#JF|g#F76x-%=5`H<}7d?fxtKm31ej0_crH| z#7X;N4^CR$JXtC^M>~rp%8EqFUP8*8M-nCb;sGg};GC+;*z7EIPIOLkPIgXlq9+4; zHz=Ck0Ol=V-T`LsW@nkR+&RrT-FcjI1~BgfI{;W8u<5|&1B?E#msIsCt*SxQs9NHj z+p22y1M_NyZd^@mUF`5-!-h?3jx{w8t6ET5zaX}#w&TO%%Bsm_!$vo(7@jSkr;%Ggi>bc@33K)t&D?PrCc-6}kz1xO=R*VQEuUthu)*%$J_IO6y$dJXMvk$$6slB#XT@5@>$TVfSD zds(b5R@D-#o)}v^FV<929jkAtt*J$BD|CA4x7vpKDNPN_YOArFbitC*W$l2LwKOfQ zYFXM8n~qNy(@@{i)KFJPuCkPj9#dJrtg^Z54@z@g=e$6bvB7z+^E@Z^dOii_Ghja7 zpt{(3k@I3)Y@GQ57+m1t_>$3bj?1bl>oBjn_AjQ!s%jf!m_<+fSEZHBEt4ARvobTM z#1QrRmRSuAi}#2Hc_oovR{`^7y9RV#>s*flLlsxGwGL~|Y;(q)C~m$2MqJ&%gt>31 zYN(W-ELVd&X`c7$&tF3NX5FFX~o_K2|{k_gdh=9A#dB5`k=Y!6NoDT!@6EHsm^9wM) z0)yjAzi-Aee@wN{xx=|r^$96?Tn7P|KY>-XPHsJX7AeB9l~q{Zv&UeG#+s%y)Yi9D z=#2O}(kqUxY?@x%Tsx0ckClKGt1fS7ER8LT)yY5=VJ)Rjp0^MoD=8{(XwSdI$CQTV z+7<+CVr3)Vfc!YB4xdwxY<4_+?nwpN8M#AzS-JSXlchR+L3Lf5^F`+#VEzK;@797@ zGit^StvhyT;qszc3+k5-T`_%V=84LPq4PE8>#B_P>xsaY+SXgn_etA&+xd?3UFTls zd%z9^HU(HUuoSTLCg%s(w%&7o;-@-v3Q42xaFc6G*``$5B-gZL#FpzgEcBVKSyG_~Nuj3#8zF^08^uKzVd26lU>jT~xGG)qfK3B7 z1Z)^zwL?tI8eLE{G;`9>+~sARQynjn#Gr2=2{MHRDSL`JAwAHmus-tXDM+h3mGW1kO+X;!cxo!t` zIIy{0tEWS@E1A2;b#K=?dBF83lIVKS^^ogf*CW6d09y#`;lLiT(e;??an}ylPGFA& z_9$SF23A~~;6G~mNOk!vsmtBK;!63m#tp9?nm=)9)%?tZ+5)aUu9t}3oNR#F~Al9TMX=2V8;>p^#NAXKG#Q5 zHH|0LR03@2|0el0>!hrlLa|Lt>feQ1cec5{bA1o&F~CmfO3SkPi9_?MhE9knYqPt4 zcKydKbN#b_kgRZIP?&R=zY*b&mhW>x6s9Qwng-t?h9a-{UgITgB^=sT z-BaAhx~IC!+~xRrI1nkAYULt;TDSQdW(mb;8{SCMq;%2zhVO6sd)D=Kv1{Vp3-T|IhfOG`t2^O&Vg zP1tV`uOq#+c8OcmP_=Y1{!-ddB|Z^<8`^%Cp7J*~)>5@VypNK(++MFQ6a5{fwaqPE zd!QA%VZEjkpEEVKWNEBfDWgs~>sk!sv6o!gRJCB`e&vzX>l2Exf8DZ@be8e`o25G{ zt#qEd8ij`&t9e1(jn!OBDsFW9?Ru)Do_{Q_#2#5khg`XTt$Pu<|3Y9F#@%(m;vNyl zi?)FDLsdiF(#7>9*!62}Xlj`dTZ#2+>-uF;Z4>qg5jOnE+Vv;N>(J2DJhT1# zInpPwquVU1Quk@@HE}nB-UMuOd41*L*dEnV)iU>5_gTkJDx0{pg_OXkrl!i38{BJE z_o-G&sm>v()&Ywz)Lb^RxJ>%?0`l#Jz@oi|+3{DbsIEePR!Mzxte$jFm&GO_txdI6 zV;UAWRyM^X!_0lDd(8&-W$w$}R{*;b*b{-p!f2jZT<(+Vcs70-HLtm)3472p@bj3u z%4Rw9*O8>xyVtwpz@7~3DZrkJNoQpZFUZIg|C@8)b>Hj0&wao9f#cDaR5Y>O7c{e_b}_b&%EgVdtL0`qZ7RyD zwZNVU>>0pb_-|7X!BIOSrGK=lRC_RYkGLOoKZdY%&E1sBmIc6G0PI=Po9#f0%e@oW zv)ip__bxZCHn_q4l>2n|Gr*oBBD8LUd$;>J_w&G>3+#Eop5K~ZwkWo8W)-QkNk~_P z&RkvF+*nshnr?@vY(B0iR#UmOu4TrUqKTq(l`wqG{rY~z*5-agwQ|4jq-)=DqeIk1 zUPF=4`-{ho?swepy7#J99^^XAq*xmJr$>)X(e(2Dzg61$`)-^<*2y{I{>c4t*DpSE z;|{5vulUOSttz9<{k8iWU@rsq@;3K(ZnVX)A-qTg!0>jd)RVO9&^n`=8kVDrToLKX zCM&9~oZnQrxU1~^+5HEabnai=zq)^O{|@Yxz+MIH)xch}(fz0UFZbUb6|mO=dn>Sy z0{a-rW?_3ayJn>Q>rpK&O||ouw#1tE6Q~usBik=JK-#IXI!U!HsBP??d~nanN1;eu z)=6;78g^vQS9cVosJ3EC8?Wt_U%9G1j0dgLHV^ATr_go4Uf<>sJQ`rv1KUOlq(cYG z(gN?)p+(vyK)XKgc#EE{@2Xk$c=Rf5$`u~NoJnOXuTQ03fy%851fyd-A&ze*w z-nlH+(&n+KR(ATgl7E}WgKEiR_c%OGNiA&vb|bKxWVPh+dVC(gC*TPJyBXLmz}^7t zjlhcW3;&c_5(SGVorp|X|482qCEv)pMfxTSzwu-Pi*h=7z2eDpuW9q-d$0$KLVX)1 zoihp*iGt#B_zz-yNlzF-u06_wUD}(0y+za^*_n#w$ZG$nlwXktBa!y2f9&gF{cmq~ zPIyW^I5M`$Gto22Gg&I++ki#oaEDUJWu9`+G|zMo_8RU4_AX%W2KHWHAN(hEzw~-@ zyA^U}w?dAQLaqV!o;M*(+Y?I7tn-}fInQ&x2ld~R!0rO}DPU2@ zJ@?Po%w^qb=BjQrgH}%5b3L$6A5zV1AV_cYV3U3p*xh1M!`Lalt|D&b9Q+E$XR2$l z10h$%jU?e#54IRo<1dg}$j)qU3pv?}L8X-VcF%2Hl$z&G4~aSU+$D9xJokC-_dMX9 z;K5pbsZ%%XWnf^V{|8MIV^|`0xdBL*>dm^3}fqf(H!Qy?Bl+8ca)A79Kd856j<9QR< zw>lcpJDv|oBYM}f*Ylp#h~5VF9bn&88qq$_N1l&8pLnna_X7JKusZjIYj`2Hq0Ze8FYi6WfFj_@7@?2o`j2v^CPzFm#Yq?7ezF?+{&$D_sUE%Fw-fAfw5 z_9tMGGqjk0+2}3t9^;+hEd};h;27X+z=?Z*{}(Ohf64~-PW9pdQ&$_vimzt3e&q14NWek2SZb8ET@obPW83|M*&BRvZ39ooYl?1 z^se!)?N+#FlfvcLj>0|Hdod~8^StMKFAxit zR}9>E;3fk%1-N6yZ>Ex3=!1dT@8`z|r_SCF$+IN+J7U%UxS!u=_F2(7^_3b>KLjs7Pae0T4@FL(de?I4(_xUQ(faWF;1DZQVG@$=OgO#!=?L$w?1;CX` z*<668w67MpiS4Geug-^yB6sty`<95_b#9X4T|baNT`9@sKHQn2lL75J$+xQO7pMBr zW77GG(|l*3hVz~7TLT=He|eklOy64IrUAE((E496v3=+IEyq^C-run?|R^7 z12?D57x%RRHy60$Nr7~@KYDU9|3gk`^g}D;C49FKk$9tTt8bem5-Wf^0k}#*L+BY z`x{Xmzx)31{R!Ms;FbZmTugt6roTT0@8ehdDL)O|O5jce?j)%e4$buUALiHXUo(E} zk6;5krM+hSX1^0_#&7Xk{Whs)P6e(NIFM_`@AA9-9>3S`18y~NrvZ05aAyE_)<2HD zKeT_%_@n#Rj6Vav@ec!T&7stcKL?Ta5BKK+hw5{!m^3NV-+wqsc!VEKptFHHhtxuE zroVrbe{>h!;#c zz+DC0)xcc?+_k`6cZ0vd-{@cBZ}K<$Tl`D?*z!@Q#eqY0wgI?}z-> ze<%j2RAO4`PDAT33`+h=i}4ICV=-)_IaWOiFPhtcV_C~E`bYd-)H;6fuU-$_dU0IV zf4YAS4%o`^G&nN50lzszwQ|~|GW>^h{aWez3Z1)Tbjg@87{pN5Fn_Xq-;Rt2N7g-} zBLB&X)_<=5ysnMpLO=S2;(lxuo8$gVfZIZfNgG?ySc!pV)nYLfNdYweEBset9&eEH zc!vM#Hj=3dofE?x#5kt%hDEXZNwsy;E9;iVCgQ}KSd;SD>-^VueQcY5E2-lRSjU_E zoBdn-H~16&8-d#<*6~fi-3;6-BRNN*jm2OM4U8gK`^`@i+^lCU8mmqf70-~>_wxOi}< z0t-X}QA`?02kzN;0G(bqHr+`F1u`Waw7Wug_==$`$aK1)7`9e3ba8AkPK(7!wN0@` zj43?2u5xL8)q=8Eb2E<0PmR@#$ghc2=2zup732@kR34ra7~b{a`GJvG#({!BVc_t< z5rHEEBLYVSjt1@p;PwFbGH|Z~_d0NI0{1p>@7@p?6&M{D6DSH42gU}*1<>909&l)x zehu7@!2Jrm3i!i-*LQt|iP9^)*f(`2P6U>shcQ63wxupc0%bev>A+O!0WYD?=+O1F z6dPSqU(=A$NEAco!aq*B@hceKbm%wk`Id8}TfSDID?apFwom!(`QDY%z2B(Nl_z)a zg9mIMsK{%iN4=HwGVUZ`0ZOYA>nY$!V0HvA053bm-6M>DHo^ z6le}C$H@eNmcY^gnmq3V_W^JpZcv>bSQ$7G=Ra}#fcu!JLk~tLR!k`^DJ!oiE-ERX zJhh^%xU_godCBBS6%&eQ_H;qW&<5!g8vUMu1 z?7Vz&VszH<%npd(2%!1Y?PUV*2KENt1AYMT6!03wEWp)cHU#zsJ_>vc{6OGSfLFH` z;EF@jN^tf%_9n!rw=$ehk5+VjZ4E}kVNp*j5x?mg361llrj;C5TVLIMqh%?%ib z-*GFcLca8`-W2#M@O9vuz_)?#fTw|HfM?4_Er9MCa zV_e!u*5!=LUk6p_HQDctlq5mgy=J5ITaa&mU*K`zx%pU}hS#NNb8(g|PC4sbv_Wmq z*dvTVbI^jE@PmNY9t6gq1FJUZ1YW1SXVB9H#-KllCQ}b>Hy92^$U_Xk<4CwzD#5|z zW`^E8hA~=%UVZzT`$7JSvFu zhTDQi2S);L2i}3}wFJkIcXN``JMc82xyqQ_l*;)r34`Ex9D^XMX?5&%5G)PGR2jGE zY{7}aNx{j%DZyidQ-fu}^5C@K^x$#98Nr#sS;5)CIl;NXI_!8hJ zkVn@9=LZ)AYl91ei-L8*#liYuL$EQpB-j*e4z>iB2A2hw2Ui4F22Tv06kHWN8Tg67 zp8$L_@Mi#jCGa-^{|N9e0grtD3<3{=9fZLki~wN@2=hQ_0pTLMpLEi4o3Z5zD$ycE} zrEhtP&C4z*j8zwO%Trc%US?K7R_5@+0-PtAhq=n@AyYM(nRzuiv4Sp{S|?>H(AR>( zzDH$#O*J|NJC%Z1P+8eo+1UkI_&2{Gv!I|bKYMtmOWJ!bmGiPQt8%*J=|U+_seLV| zSY=^NW>z%@>2!Lal&7rx;n^6MjFp>{os~B{J2R`NOy%ZOXI1AHcFELbQl>(E%~bV) zYcDr9KR>ImFfThZw=ge1Cp$MQt5e2hq_Fn#V+HxyT{3mGl&Q!+UwgU33$lmj77ouv zoHDcWP>|+!%Tuf}FIJPC6RYZyr}a{vqJ7U(PGKxNJG-)5?IG9MdBZbvaMAnl5?TB;{$yzoGJyYI?ECSXE7KUaU)|Zj>^W(bs}PDKoqvzp$XH zTR|l!qp%?qX3op)lBZjwJfTU@H@S($e}Kx%LAbH*hG%AFA@AA43$yck016v!btMXu z&T{h(DNorI`hklS!HF}emx@b`jm60{I7tY7AsLg(#>E;I$6A_JqC~HszZ5m)h#BI# zM3TFB4Ej_`}iPe$0gu|xb z45ylgrp07gFB`!VHJgnozG8TlINydk^Uo^B4=lwO0*nh<}%Q=gT=*AZG5r_INDL5xAOML-Pt!x^kXcDx2oVT1KoW$g9X3J`^jjE;dxW zC@V7~D>u~A&`^hK($&^CkEm)`oFV?6QQeZ!{(Xj6Nb>Q4=qe96~yX?RQKcTh-<%Tph`2TxSLw8n>&=Vo`cAit0@H6B~& z>;tz@vT)D;spd&u=-<#bs~0U=yt1xpVeN|A>Lqnmix$O}RM#(BP+PTR#k~JO_pYyx z|IeCh-%7|G^Ut@<&Q8$6g2FuXTlLg7=Ve#N^1FIHew6Z5+Sfe&PrXC=xw$zp^tLG@ z7r&$q#5r8SUxU8|e-Hi<{4@Ah@b6SrDvqj60)8^^Q-D7f_^H5`0bdUMG~lNvQd6W| zR#F*hbAnU>_~YbVR`{9in-lP2xVxjnOCwD~%8=p&(Y1rC|8)OxLBsNiwe_`&$pXs$ z9)BhdpD{#_qbI0B=k4(tT+>2Y#u-P*yWa&@J!)9mQoI5kKqTA-uL*X)OBGrCTMWL- zXsD^d*wUWv)ZFPRvh?+VUTM_QmIb&1SWiC_SJv2ux@wGb6vx0)tvCRbY6E_Tyg5Ot z6E`Q|%_*(qfPp`expCsTeUeIQAT<>?CrHIXo>}o!9Os!$*3EJh#p+rrr9v<5`o?nY zr>3V4!TCKYZK;FFW;_fOq+(mZKJ76*; z&5@~N5wz41sYj(AojNjgRO;x|F{wqVILK59{5;^RfXDHw81OZ~&j)@1@U@B5aWZHV zWY7@Eg$ihO9iS~Cqip@4HDlX36wqc9(B=TYNC6Gk72Ze{q_mO)2CO5XiRTW`YEl;v z(6E9Q$5U&8uTK)R#i=-psx7r1cfsHr$SxSEOK=wqzOjd0F!U)(L~ZKw)DtDnR*IZ8 z;jn7z5;CmX*o{sFv)0tJ31*PGI`y>F(^J=^o{@TH>e|$^fNueQDe%jHUk>~V;8y~F zBJd{xzbcV>j*Qv)GG-S8f3kwvsU4V|-j5khEX_Dn%&sSxtq1-T1+xtYm1j4mZX=j& z1-><&iX+F6Bxc)F?~vr#?V>zeO@O(J0D}t&9^)TdIPPJJfz+0@;@p9%b0;E}hpfjBZD+1IIL->B4Y zfWJ7NieWpKB#GINsbt@%RI+arf2kbKvrSq?=-THK+5*C0ira!f?)P5 zf%CF%aLP&2*faxTmd2&=X+oMN?Xa{#Y1%YhnjZM8fWI2}YkPJ8ph^qP%y)NZWYY7_G8uu%+kV$Sy}}6jWT9wgAuc|At|lo03P?K(@JOD z&r>m&(sI&r5wtW6Pudbs!|{$}8B0sdCtw*!A0@V5hh z2k>_Se^(-Hh78&q8MG6Czgq$A-VV?n>Ibbapw$u376X5e0$L-2#x6@~B?k;VMeGKU zbGvnxwmfYm!3?dN`{HS6-Q1rfW~Zcqgc(|W*bR7q0CO6_3^&r-Uu~*$6=v3^kzE^5 zo}DdX_HZw$lq46XT}?2%DDC33OVTb)yDaVUv@6oCOhaMzDDaN~|2XhFfZqxH6Tm+S z{4U_1N~B#QW42z}Z82>l@J}n4J*(`t$cqcL_V)n}(Kt)Hl~9IF`x%9@JCHKVCn>Gu z0QyQonRxD??EbU|31trezdN4x5b)0>N!ep*J0;3?h?G4~czKdg_Cj~cgpU+to=tmR zqU<@5vOT?|Qj)xqwwF-$YT9dQucy6{_Ga2!X>X^!llCs~F9ZJy@UH@orq}DhzXAN4 zz`q6j+ljRIWXkr*!t7Jv-%%*r+ab(8>=$Nz5oZ4)nEeR+y9#E%5Mg#d3Nt)lAX>lZ z(;(*#%>EAHPMh(N3i$Wpp@G1^pB!c(I>d>Xg;)`@4-lAxbQ(k2kU?ZDq!$_6mqZd< zD1eNG>>)?U8FGc(Ay3E~@`e1se+>L5z#~4N0slGhUjY9l@LvJ{bs~ftE0I5;u*6ts zF!0|fjNzJ^ie)D5c-Jq=4pEea@{zGn0r20-jD?Os#(MReg+_;p2xA!R{CzxxuBac9 zWUM4qDls-eWb9u_IKV=dMo+KEmxJYc}xM3RZ;c1adm6FQSnb_NLQcxWvMRFagf3!N`fb{?TjpiwM^ zE<}YXFx?cU?gv@ zlDryvkAU!6==IPWp*KTsh29Rm6M8qa7X$|gP7qumxIyrM;03`4f**uHBJ{ot!bh^W z`3wZyzK;9>A+1B);O0yH;^xrB&5wkHpFl`eNcfc)PQCR4!>Ta)nd0FAAcW%K6cED6 ziJLGJ=0$N6=0tH5Ik*)R)`g8CV_}2HSTuKjuq*5id&1tZFYFHoKo|nT zP!KXe7zRQn2w5OxgOCHl@I*LOVk{hy7z^X2xe8j4 zlBl#DsM7F&0e6X_hMe1_O?XTgHz<#Xi$ExdhsT0Ym?UGzgeOXjm5PiVo&+#u;pq}% z(?rIOOd`pga1CK>Zut0cMfikpWq4k=DqJ0ofp8QEM}sgDgi#=%A{_$)zCtkwV-w-| zGGmKm#u`8vr!ZF1!PumJ#`?n8NrbUgAdFWSI~5tTe2RVsJb=E6FeaWm7&{}pmN0fE z2*MaS zSM3Ym4#F%2GYbfFK{%dh&We7_`hwZR1hYp#n5|&;IARvw!JEke!WF%&(G=(Lj=>$T-9>Pv#cXpx+l~k{V-zOlv9)2VIX85h}+u?V@?}qn= z-vglvglZ5_@YH}XAA|)U)Pk@Oghh$)2eQ2RSe7@RgHWe{P~RbMn)*TL3kW|E5OALH zVg-cX5QJWx0g(Zb6qGlSfgm)*BWe&Z$RL>@ng|;qyL_j#MR-x(EJ0>cGmx1cVrXPw zBKn9)6gCl~C~TUONaBd3B4ZI}#1(NzJP~ii7x6~|kst_5L0AUDau8O4uo8q5LBQ@Q zirSMCku*ivNQ_0$zB)x=%+kSFYd>RsU@TIIj71Iy;Z&Ki$OvSNsZMDn2Mo+4I!!#c z>$FHwL>iilh(mJ%V8usDhr7;T^cvo<0P%|*na zIpGo_UwRKUh+G&ULvxXfA{R$4iCh}FEOL3|ipZ6bt3bF6gv&v=0)#6;z<*v1!ZjdV z3&M4Yh&(hGx;YXTwyE|-HiB@y!WbGe8z5x?F=jUQGu9Wz$k<$DI|%C)#>m)Q85lv((ec10T3Pp;UN&v2a4AGqaZv6!sCf_+)|$WNq1UaN_XS` z(GR&p!R$$(*MsmZkvF^hG3x_n=@`irPe<3(9(}eA0>j8K2ikjX+$QSESV%c(_J{_T&|m=Jg+2O9D3WH zjze$QPk*kLbV`z`>2nBbW$ESV)6%D>AD2EOeP;Ts^w}W100PRjJs`XU!pk7M0>Y~x zyavMSiS)TD(RdEsEJ?I5rv9p1vb}XZjQAPp0nz;ad>C1L1oRP_OM{)nf4 z3BsRAGWKoy4}`Jr2xEVVjAf*3LT3(6i#i}=zov^;)An?%X*+0CNyK(U2SzDeGccMG zRfA?AXw+>{I?8~C2F=(mi{3>w;*>#6N`>x-Ltf+-_eH?zWsOY@=&NjBvM#EZ?nouQ zF+#W1e>>k-Tr)Rnin>%8TcYNuC2Eb@qV}jG>I4nG5DOX(G(2bo&}cw&*p{d}>WO-z zzNkMMhz3D32sB#IxIyCqjTbaN&=eCvJXBn@CkIz4S{SQpk*2ZX4#~@E82KR7%h4h`c-qDl=mCdnc={^;@@PV%`tDRqulkt=*hxBlzl8hn*rQ>dwzRHdb+)`Dr6CEY(Q4aE^Uz3EycGC^^hC+_MJ0>+c9*xkSx(GWm6V% z(TphW=(;63ESee3ie^W1qQj%PpwWRw4;lk#jG!@r#ta(Emh`#Nf@op%@aPfIBcmhG z3<8Z6G&ay6=?>6fExSm4`J@MSE9aJLaZxSq57B@dKTN_!9Gme0xFdGQjf%S8NO}C|?mvYV9U%8* z;snnr4YllS%h3hyyWRJww9(q=!sw!C-OTnm zx1dP{4K}&}XmHJf|A{~ej@miof-^oGa;=h|#%K$!^BP?eZHhL7CJi(p(1bTcmqwRG zmxCq(nsm@a@s%YGr%Sk2=mH0P(N5SOxHP7T%Xmx0j$?}PXe($2xA%jir$uo-;O6M* z(KXRCqGv|eM$ZDx5YP+-O$KO&fhH3)S(~Yy(RC!Y2LFEn3Et9VldcZ=i=V~K3_E8M zg%7S4*RqmehYaE(aVsaHknOb2t50MV_j4C7tc_v2O+DaScDY5c(`CwY#63T{T;=X` zRaZ8oj0DHv)aA-XY#Lp2veJjUnZ)KdG+~yc61x&tA&y=JnjCRSVQuu<=ylQSXHF{1 zXl`jjDFqr_8_hqUw6=Z`{%h5$(xQr~(TlmmL9vwz2@fV=IEB_4bepO#^~1Qw&+dKo1?cxZ;ft`-WI(b zG!V2B^4zTM~y4S+)CHqCthzK(E0k3NoD1uN=wDpQm%VYye_rN zb!FvKOQuxFR~HvmOqn{lXxf-^CCMXVl3 zW#(}?^9L_#>G~(c>m388;Ci=}^To<3nKX8?v>5%^lG0-3#!rbCrggqh&TPf#X_Jad ziz{#m`bp&_V@rysDrue-)7W}SGilVs_FF$MUgjGhD@;<_xE_94$+$@sS=prl;U*Ppud=WlG5yTwlL)PG1*qIi;_+99KGd^r+H`QDes7`{0vGai#yx zw|`5#eMDS*vU5(AWhqy!Dm$)ZY;;Cfmf2Ek;6_YuqHOHEU;_8IBd_eW8RTIlg z5e?i?U?R3GsbRereIGX?lG?m%`Rs2QY>0jk{gCV!)ca)>IwS5Vw0~knfPWPIxT~7_ zEcy-Zp%(o-`bG51=vUFNK{F0C<3UpbnqxpSVN>+m=y%cYqd!Fd1)5UOOa#qr&{Tsa z_V2gf4$*At#W<8pw8KKG(DiilUQE7&nOc7iMoWK7^sngOgH?kE3?4W*WiZT7qDyg zsxgV0Zj2>rz-~-$nwTDAiYa1CF~)S$O*73Tzt^4FSwPV@zCYi`#s5QYTc~Px!3CEV)G?kovvQjpqry} z>Kb)Tx@MxOCz?4#gDx;W&m)=zM6-x!mh9He)6Lf{&@I$0(k<34(JdvK>xhOB%_^d~ zg=lUgn%jxyE}~i2S%>A)qdFGDvB)~$b_mg9lWi7DOkApvmSl?;Y}OQ;5SJ8h5v(aO zwiL4|KGhNz*WsC8ccYXL_65HrAyb?+DK#}UNx-_(X2F(bi4~GklC6R{DH=Dt6jKV; z3GbND%~C>G4(HN@ET&j%vNcsmPO_v5wwOdD6l0AM;!{jP=rl_wiSCdRntNG7 zX>qYhSW!Arh{2VDEiuj{#6_EILTpl6Vr*(^d~|Y3Qb&pImJ*tOSwhe&(UxLM63nrw zuu+mFPKZm4Hw($B*5stLRCBB)(b_Sgd!&RGUY1a7ybVjACBi%=DkI<_gCK@!b=#ekK`ejnn@+56q_7lwtSKJ9EAoxk$)4}_72X)Ud z4a|Anjk*`GQJ}Q{VYbs=hsBes8=CU5#foG8RIGPRG&i{z3>P_x=K5p0mvk>P0lmM| z9n!s0tPRATN%CpZ`W@nuP1-D|qn^Y9ddCB*GXgBYT@LF`HC zj_BSj@;so>YqsIgTg-yoDOvO{>7;jbM+-Y-*Q#q{7IZuyopoG?ZN++{?>wo#^3o2~ zHr+|xDcT#m!uMD0hUwnZec&lB-D#p(E#K-sqQ*T-G;6vt?#;R{W&1S|&CS$)Uoipd z*S$7U`)NBUBtB2VQgT6mtNWhj_Z`vPdJWa%XC2)ruw$i?)B8jBmnS{lMWVSwmj7SK zuSa3r*_HhF=rL9(mH$GbS?iJC_m~dPIPIvix)N!pK2#P7t@TEaNP&|(i8NFngE z*}g-s)9dwu-k`^D!%m{vMKrsKW)IO|*VGQKuD409zPVVtS8nO)*ezX!Y{aGOz+<`d zx+=%)Y9p3G&&V=f*3B?_x;}LId#nTIsKkT6L0n{hEOtI|HsLwbG1@GyDCum%aKUJ7 zF10(2?%)4G5ouSGD;ES^ z8nN32F<#PR$NwLCh)Xz1dc?I?D63o^blaK#pocgUqMxXDj|ICMM16*SYNwu~K1-k7 z`9Pi?0iGQmO!S3%_du|mMzP+G*(`kt(d=u{mlDnWuGk_vaDy>OX<$tn2bE8+)H|8p zd-YZNYW*zzY<-QsR$r&D*Ei_VGkuU~9wHjt*B>Do+}9r?n#YOe38KOH+5WxyMtu{F ze9+I+&(|-|FVrt$@F;SCXr7|M4@C1c(HtZi42eBUG|%BsY(6S6c4xr87}$$Y`i$Kv zs>>YmZW;yEjj1)&mDQy+7$WW6@r?AwylN-fCOUhg^(2#PcUIf$(7o)Gn*4B6tnDG4 zndmI5s&2x}P_q;1x(`Y@r`c<(YjF1s>X@0>iqNGaFB1YzTIO^#ISSf0p2(Fx=7_&A zL|s0&sa#Y_sKHcBjevb78k#YyF+%*as=l!)SK6Io>h$W#_A-k}Z-2XM&C5h{hG?*7Y_Zma;!G@Ss-9cjv>;R56qb&8)i~&2 zS5|XvEw&bsN;=C?Ne4G!w7!>J;vO55dLErq%cgs;ioG=b=HTmh=(p&%>hIOJ=y8ua zL^K%kdz)yE5zR@AsLHbM(BsA6ZTg-1U3%QIa2q~MG_P*c@73R@-$yhUS$v&n-k`D% zyG)QyqE2;IW6Ze;MWVa!=@CkKnf;hM^~d!m@QSqNIMJMNjc|)Bc3k!E>0ZwW?7h2G+{@NvI?gJT zDz%rl-}Iqa@RTlAnm^P|Yd-$U9@ z7{>=_1ABM|?Q@5g(K%LZoSxW(QT$R={YICS#FwbZK3^sgNn- zf?HG5T!F40t>e>OJzc$ALD+&E0?3)ypycbF>E&n+sw=7;aG5@yZ?hLPINHC_GFq>; zsnasE3Z$~EgDIy=A048dtI_n-*P)SV&CEstWQes2SLEi+^gJ;oI-T|f+j6I8qwK`b zsBe-vsPRQ@=@6V~pw!w1Ot`~((s86Tqe!&s@(BpHQjeJw{n&QlV~NbgDg^I z?)dYiA7JKC8>&FgWjdu%NuLtd?QeQ4HgKuB^e?#4x@?aXf5ZQv>}x z9-n*7&dyB6=NSy+qj6u0!%WCHY?11$E(;xpA`cyB$NeYNVzAITO*(u=Px*iQUu{h@ zm7D$-0yK@YvnJxV0rIaXx2Mq0arpd5nLRbj{rT&;)wxsfIe}pmLmHZrGVyr=K9@Gn z&Pl{)gu^TLRXEdf@OcbAzgyKjo_@A5jI#H_s_Z;`9)!;m>Pn|%;PVK4t}1IxF2LvE z_}p6MNT=lln<-zfZc5L_XXK~+-dUeX&yQjl)u?huN~&~RRWZAMB9&nXjz88oH;Wz@ zWnNg7Oyxvgs*|(q6Q<%b8Zp%`j+$}we59l9-_SIbris7RDRnhdXub*fybd8NRA2n9 zKG{^2P0P%}FkVBNoZ0kR$mWIJ!qd|6ISrrZS2@Si^p=r{3;j%kZ$Kf+<<$aLJW$lcEsb@;@vkZ?HA2Xp$BU8=H6+cxncBU4DLIOP) zhqLN{6K6CsvvIr6G>v*d|Dx%h6Voko z=Vw5E$%A$<&G^2G`4-<-;nQU1taxNT}eou4x z%AHF+t|%AtlCGm#O0p$G<~n8}zN4~wqnmpO~8%ig~A{8dV=y|m=qg-+#`(Xn2LHKqKrdV##uZR&T_XVk};Q2hQ( zeL{T>pFU8Z#=rMG@=WbeAE@nV&8f!EYUn7}0I6n`iAQKz)Zia2m&@gBFEc5fOHyE! zV!pJ_CW@)h8deKv$vVVx9f$nwD33;1yBYPA)(rtQreoPjxpeS=!;260WkOG`dHyvf zbf5OXt70yqwNI$_&p4(zyttz7w*CzbGj}fj%hAyOEiDJf4O1>mVV3Dl51GC-Z8z;R z{cJkZeun9k={wU2QwzTNMtP_5apg101InkAN0?Cj^_21jsy(-MpGS|+;ysB-S42GXfN4X^nAIbX1P7JW8I_n?O0=IiFHq+jwRZ;MUYBI z^g2F_H}l?n6d%ne@+?0X|15k0K85i^_(^;pd^?_x;8XYk9(zbWPUWEfPHULlF0{8| z`S@0@2~@u-)B~s3X4&2PUaDhgCoO4TWVi|Vf393OVvnm}eQw9^NN>oLw65O9@Yc&f0Xj>(< z-hyf@z8#}VQN_`AtfK}G`4>#VM&guJQ0&}`yBqB@(Q_E)=V@YJi0yr( ztl2qNI;Nt()QlhcQ@xmexT}WYZY@BoSY{;dnW^XlWH8xGJ~I<~RG}oDuTNo*#Y&z7*2Y#rOoE@qdrtJyo)jcg0Mhkckmz`nq~#vWzgV?SoU zVt-=)R45f1MK49LVwl3Hh*KmgCMvQOMT$zr9K}M#3dJpo^@>)-KE)G?7Zh(OPAJYQ zzES+DWR(8O-pavBK^dn^R%R#*lod*+a;b8aa-FhO`2gC0!^&gIv&wIkf2h1vJyoG9 z0i`%zm7^+C%~35?tx;`M?N&XZdRcW$^|9)_>K`?y9;nu-N2t@))76#gdFqwwb?Tk! z$JK|>LVvEl;N|7j8|4#=a?AIc<+aFbjn`(c2fd#6I_mYQ*RS5*-u=9F-lM%UyzSmi z-YdN~c<=Lm&b!U~bMN1M{Cz@vEIw&I1wM5?%Y4@P?Dcupr_JX}pTB&yzTv(jd^3E@ zeHZxN>bu?dDc`q!KllC1FVHW-Z?s>w-z@A}zuxZwze9ef{eJfM_aEXP??27I+TZ2B z-v1&0SN%Ws|3lM56QxPk%+NGzZqe-0Jg<3A^E1bB!?*;lfNSDz;r4JZac8*S`JTLi zPv^_|>-bIl6MP&0eSmL3ctB#n%z%Xf>jEAPcst-*t*>^NHd$-eF4b<*9?+iB{uWZ%SR1$|aBtvif#-U7_ZZeAwMTi66+O1~c&W#yJ(WGfdM5WQ>$$w=_MV4&e%{Ng zS46M$UbA|w?sb2!w|boq>JelM$_<(yv?=JBptHS|y@&Nq?_JaT*4~fwKH2-vKEZtw z`#AdC)aQXdZGC?0JD_huUq|0neIM+5qVJ#mLi?rmo89mBeoyxMu)nH*RR3xH=k?#x z|4{#L2lN^+azNRDRRbOw@cux>z^H+l0~Zb4Ht@*6UxNn)j|*-H-Vpp!@VA3{4@wv` zYtY(3&kp)3q-V&Okm``NA(@`l|o?8#y0 zBKk(8M=XrEFXHrYZur>YbB4DLKOX5785cP_a&zQ6h+&V8s*2ha^)`Z9VszEI&AOv{ zwLTtWjjj4qf<{Ob<_h--9~*ibCK;9)o-}-K9BM2u-flc>{Kph+s=?ju19K1a1oJZU zQ|6y6QI;~xCd+XvXHBzSXWei8(WbLGY+G#aM)!=K9DPIdi_w3_#Kt&d9*FrWc4%x# z>^-rk;(EnRjaw7o=DgL_ngYkcih#Ao|;*k+Qj1)%B9=Uhqxls|L9HX|6`gHV= z(e}|TqtA{B9aA#q-Z5v#4jyYC+dB4>gs_D2gq;arCPpUCO5B(DeUd53ne=$lZ^A*Mn>uaNv@bHvnTsy85H&*{RYy7OOvwoYMF?-kSe{1q;9<24LEvY?F*Q0KB-OKfZ>gU%V zZO}EWY&bh-#GJe4oOe!i?rdZmiyHSg^}++@k>=se*EfGWcg);PbAO+gJMYo?f%EI; zA6XE!;HCv%E=*gvW07i6*`gO04_-_bf4n4dNy}1pY3b4zuM4|w#dV*%#<_MAKQf!V zxy-cej%B|r&s+Y~ir^Kl6`x)|?)v*y@++MyPu(!`hOIZMZmhoXt(&YjZMf;5RpqN* zUu{~wZuP}AWour)*?jZ*oBzF~;+D5=jk$HpZC3?4=!V-iT-;c-@x-R2O%L8P@SdCQ`E7Ig z=C&;fTOQaNymj@~Kku!+_uZCpEl;!#YhAa^YunsyUu@6aet1XRjy*g3?_9m}?_G7f z&hF0K{qmmJJ$v>J+ChnR<&ANu;?l7~+| zGVzfYAB}tTfycrhyXWzqkFR=yePY2A=bx;4^6dWn{YMW>IPl_ABcFQwX~WaI4h}xJ z>6xHsZhhA8*%i0zq{xA;om>@L&6V7&QCx8`H#*Y|NUvr&;5Sh^^5J77k{1l>zNC+ z7ykNf)$jd&-~C72ABX?U`}51c=3Vr@xc=|Rzn}VN;yk>M?C^jj!Dt0LjD2^&lD!x^mM-ReB zsZoX~Ey`Hs7-gbzk}_LqSJo+)D_5cqu||1|@;2oL9MagR$+{2Tm?+hvxz$(LMoRtR2%avCiK`o1#;q6RlRknigw9=vtgr zh>tZ}gy=MLoGCUsCdHbXBu%$<6x*X9hTRt}vRd?^rX~8&MOJf6oIccyjWU-k5hry7 zGo94&I&$fx&anS>Qs*OWfRC@Azebv->Deo&cb~rf`VSa50Fyg(HYFTEPLiOa!BJbq z$v=cq!Ftjck_{bB%+tUWNlp|MPD`h+QKA0kq^GA~5+J>Cvb`GH^dWjEt=iexgo`kI zj+hjLLy51u(FqxR?MYSIX08!mi~cg%-Z)zv^Oy4U6ij-Gls9lj-CQ$M2gW4#}7e(nX-7_{dZQNu`Y~)SP zFPd3gR_?%{e?wFA+=Yu4yU4PYH{7^dn$$vUywwtF3Z=y(mJUASFN+C-{3xr?Txc=E zY=gX6w02cukHNZ%>Pjha1Gk8dwMUY3DkeK{RF3{?uWQGQc#Mr3LtBYU=EB@FX*;a8 z=$KecUumFI4_DBR_z{?q!^G1-SBPtfE8I2wSVAH~{P2nv=8Cc~J?*HIY@3slo+912 z#Jg6bfa0Eirz^B1?3P z302i*Gc9QwpFUw?SCd01mX5i!PMGAG9-=}{$w+Z=m^h=ErXeshE;%ttNR5e46=Ks6 zn3|lL5{EcWbG#)cHZ3kG)-(f-VxpPGnM_M)0@*n!nC}X_2B|Mepr9~CoExJOAPzP< z$rcSqjy6XNiHR|Zg2ftR5|FXk78{=!8)r-Eq&AhH#Gc~njd{QBC(u!Xib^x4n$Z5q z)mJJgsfxH8ypYb{b+o5=hO3{eziR-}ShOfUK1LrZhz*H3I>tsz$Bc#qGy039cLmYH z$i+s#K)Kb`dt67#yR~l8F^DzCISX@FgWL(nnq%dJEw(tT+(LCq*sYh?bkP*%&7b88 z#XK)W>x&i+7fF)Ahme@m#9cLkB}-?y!dycyOTdDv`5#rI5-eXa%QeguK@+%A8+%0o zV49m&pdTpSvPMMx_B;TEry78VSwmK=5=)GzG8l5 z{n_3a1~RZF3b< z|M;Q%)&oO8y%l{G{S~2#A&Q|G3>vP8Qs@;{#S}#ux^k6@YQ=4e%@_*0A45Th6tAKy z_pai7#c9PErCQlT*-tq@8H^5HnlcN6K{J#yl_km>lxvlnl$(`Xl`YCwl_!*^mA|X{ zs|I2aFcd?5IjRCxwW>zdsA^WtQ!P;4rFua1xavvO0oBv0ld2z77gWEi{#0F5_febF zvFdpBNcCuSp1MKZtX`(RUh3g_I(}<9cl^|A+dF=OO&Eja5`<_WMu-&<7%hwtMhc?@ zytMEG(VQomABpBCqWPI){I&-jiUf=fBninvija!G#?em2?}S@GxP^qf zfp9kxZWWGkH`Bg_7R_uHcDI~jpIePcMj9JJ4|)DfbUM%l2*jbBrs|sNCcNL6S6$wO zcMj-j>2-|_;zW7-X`U;^(`L{Rw-iTdb7du+L+?4+QCsg^fSJ#Rs`jI@44xcl{FU@B zD^1tk4HmM5B5I9nAxFp+@`UL^zEB_(3Nwi252E>#X#OG^#KithH2)CIzl385$L8b-GND{>2o;1=5RM~UAHww|To~ajgi9gZRKgWddzi$R!3+>U-nSOB&Gj`o z=?0Ht270$ePYUC#;tQzKi(&MViPcRVPRm+QTUw7-Bm(7ta8C-D+#lzxZ*Gvjps(D? zua{k(N_t~sGkwiGn!*-!j zXcC%*xr9>^PDMC1;k>pB^COFdg~B4jdDHjUIX}YrQ+xKJMLEC0j=oKKdXuBJF&lSW zsl$iY*B!K*g8+2|eAP+!UfQE|cWyILv+%|k4tNaLDWxPwMZMD@y#$Zqpb5)@E)!ND zrcYQ-IG+~bdcyhA6)FN~()JoyGf|X6KKUjAFEY~*L3BFW?*!N+9?dBBpI)*=KJgX- z%OA_B-cC4;XG;KKt#DVTFhgOza4&rV*dS~aHVO9#n}sdHR>HyS0tlxiTp;0k5UwZT zdf^EGPPz^3U{=s40P31S^ha;JPayXH!yvd+nLLJ|F6$}Vj5->VN4x1=oHZW7D>SZ& zJ}}{oP8P%)$X#C~c0nDDQo{W^oO4NOb)5hL56hYy<&rR{x8*Td4|7y5tFq6b&0(Q>IgAv{Yh{iLv8I3PSFJS`j)o*`U6!u2QI0KyFr3O-x zTQ0{o0eg$>6OIYTg%iR_;gs;M@SgC#@PTkz_)s`QxS@m#C)_Z?MG$T{;UWnaMK~Sd z^n?=#XCRz$pKw&!{#w|%9UigNFk)}GG^-fPKm0CxiuF+!C zuRIBLzKTBYqwzy9)#aBB#CMYO)HXN~-wQWuLTIPh*KMR)&@UU47D%HxR9g3e%w|Ng z(Pv8fxaG-MEbL3wq75^SUEUZ*ThS|K=*Y-llAp?D_m6?aiaWx;2HbS5gtN686p=-Q zi^i>hdQ`tT%?{^+sR%x;MKrLpvHf|js6t%B#C;2JCui_6;8m3E2491p!QY@ETnyo2 z2^UAW`0WPX5Ma<6(0+~}+(^QWBHU=2MQ>^i8mw1WnN^0xA(E@=v49D>90L(w*_3K; zT##L#UWfh*#*d~^X~ZV3P!x z*CRBjuKc87fMK8^*f7Wt!UPyX4TCYi*M~V@K;f6><6w{zwZ_q;$$9zPumQ^>o*Q}6k znbTp?T3X)ObOxAk2{eVV?pNUrcs0hB=YH-M2ht2?gXI#XB!!SltHDY~)@bGTXzcm& zlH=``puu)h(y@lPV(p;IuI^;gRzp0^<3F4wSA~&=1X>kF8Acn%7{(GVm2hc<8%MbD z+YO0^Btxh-G@`uVlF<8n9R*It}PoP*3iZZdN@y%82)r&z)+>M8Cl>jc}7%3|WN3ZV6Yp z3I%7#GfX$+Bia_PDbeO)YE3mAB63%8JFTsR%OKp8jKCl-&)65{^A(JeQ88+E8D`FJ z%12~ottdTi{nQH*%gV$SgN~ujY!u(Pm|EWmpQx`ZYINVU#Xj1D+WCwZqhYiRcJD(V zKrk~Hy_DgMjxjP;F&JPh0>aV|4lo5_bvXzKn86eyB%qR+g`fZ$YSxVKh9w9LSkBzQ ztiquF?HJZy&)maoVOlV_znj^MC%}i9$MF>S6v70aXI^9uF^3T<@TNG_e~NjJ`H=aD z`2-;YUtzfa2j)lSSLQe7FAV#$tcvx)kSxz?F#*sUQvd_mP%bI24covrvh&yl>=O36HpUwdtiFtYb_3p* zl-`^ikEMxP7(XfEUCXpF;#(*T1~V=8L}c z&??&yTN#EqnQkjrlBbNv|(Z=s(VREDd-W(FDfVGW>wjpj&d#A#+Vp0 zriZRUoM0(28xtcX7M+hl)%s>9RnNN(;iB;f(d>45jsbXQl~##S%or)X(Rq1}Qu;Wn z^=(5iOd^wX4XH&HNU5bTscz}CiZ%oWjc3xkpGrxtK}uyJGg(SyQWoCi)B3a_EN3bv z(Ymc&Np6gkQkE=Fb{>Y#@HPO}{K;kVnCaJ&7Vb6FQUy$*Bvpu3)y5PdNT^$>NEeqd z{@cYmU}s9R@QzpC|YqXvW%0GtCA~abwTR&1BokscBO;Q>QnZ;5Xi?WiZ=4idzFjaaT#?rc- zQc3P~DWzqyMiFgz+PoftTis5h{O18u8aK+d@21?W1&z4Jv?2Oy4Rdq%lX8R|l#;rY zxy@}HEgHu=m^(2%*lmGIa_2~?tYhw$QkkSxw=o+Kg|_KhQduaavRQV8kTwia-rK!2 zq)S_6HMZrs-|TE-c3=v7SNFwmM59rsUbIK{qS0;4eat@Q{_dwylKY#K#)Gmd59Qz; zdV0Hfgn5*C>>5(a!`+Tb^MqXUqT87Ln2zsO8q%dt%ZdnX%rnfh%yZY0J(@I{{R?vA zyRD6RiFvtuX-Jp8B3B9&=c~+X7;Wx;#mWnm(l{d9vAT_U3tF&rOUHYlq zHfJ-RWj0o|F<&rW;w6G^+tZ+!W*CXnG<<~!#5Ye>Tf`O+$JUcSG>KYn6n#xXNGp{9$l~NknvK;m{HkZxoUK-M+`LYF32MgI5 zY|*u3e~XkxvE1gv40g7(dud3Qmdow+Xa?r5Kr}tN!`;1MIP|=f$}Bk*J3Bjnienz$ zSHzT68{+Ef*!u3LSCV(Pl-?XBl{R+H0&%Qz9*sR}W1A4>KlfS^+bShCU#?%<+7RBi zh+TXwY3!ELSSni>X}DN&4QYH{hWY^1Lg zGE57*O3H9G6DmF9+{CWwIv57`rha$~kHM=JS@4<+HXGv=b`)SW>qJ&-+0E=u_CEG8 z_Aq;r{fIrs{=oji{*5{C5X^a-@d`wWB2AH@C>39TSgu&5xLvUkv)%_W>wQFV46i_( zQT&J(AbiDH?=WS!(trTQsmgq1sj^x*N7<-cth^PWi@OlE_#|G7dJ!|svYV&HBsND-k@$(?@>R3P{rfw57l3&zf=FH{#kv|E5K_IUX(E5 zRfzGsP#* zr^Khyr@?2r&mBISd|G|(!>bi<`keIn$ma{6AAA+Qfxi8H2m40(j`p48o8vpv*Wp{| zOMGwh-Qe5myT|tt-$TB~eLwX5!uLDh3x2+SefUY-fE5D!o{_t1$2l)^67yM)VNBgJw=lfUr&+%XAkNxHRH~a7N zf876B|Cjua_@D4U=l`3A(fDe#ntmF+W~3%XGg*_ZDbh4(uG8G8xm9z!W~1hQ%|Xo} z&0CrinlqXoIfnD)dT{-?AzU<~TDZO3Gu#pG1b3SI9IthF z^IEh|CGNFpbp>z`UDILhzJ-F zkRFg3P#91eFgsvrz|D98WOKmIfCB-q1{@7|Kj7nluLJ(pYP3PxLD~rI2yMDHQ(LGl z*Vbw0X;*1CXj`@SX&=%)t$i7UR!Vkk-4BkJd1E(3yO*NQd zq+_FB+Q~rJ-%)>zRw9WASNr z%=&bF0-aXsG$&6dsItnc9JTGU@9wl@`I`)L>5z9b;qqDx^9VQnDiiRAMTW&)Ou$=W z5%$?>0^Z;<+<-u61Hl_F%MB|G*Be$6u8?pu2#3k0nS?7QT**$D=$^g4|F!zM5Wos+`+ku;kpPT-0Q=~d&HSX6YLFC}T5 zXQ1DGzBG?OrvT(MG0{dhIY`0+HnYVUxlX1N&!jVUbio8VfrlYuF(^T{+&aTOwB+wL ztT${hY&2{lTq)to2v<%x2jMDq7&aTWK)HLdco0`fxN54}EEi8T6GJ9xtPN^ed%#7p zmc|bxH#;%Z+ce4EjESi%Dc?+a{8yYGG2^W9_PGvemaL{`ft(74oTOMCYNaZy;(~=B767z2d3{M%JHXKBcM-CvB*EpKl?rL;dMDdJTjHkCBrqR}PImC<#`P%mH=)77j z;ZU7x2#3Wr&7R5hPHG!c=R3-p>8wg>-P~$teH~p>D5aj}BT4=oc33eyZ+OA*qTwaN zVJc@1;Tj3og!pm8D~7|+<5i{0@OnXe&N-q?gsZ1Z=W|%HRA&mMJ2YUOl+ZA9Xmwqv zdxj6I%Zm}VG_c;8Iu{uakCd9mHw|xLG8Dzp-VjRDhhoxG?bXg!!`rkuyy`i!fJZgY z8D1xxlPI5nJkztQXz7NU-Csw|rSj8q6vdS07lK-H{wC3uv z+2b8GsNf?#r(PPUa=HGU&cJ{t)S;A{M%+7A6K+i_?M%>Kgm@S6BrwTgpY14@Ze)lro1W?U#(nckbJo{- zqR`~TdmF}%|2>~9=k9B2$S4l;%qLyd!t2(!9{aJLffHp1ObxH|}UC*csE za~I*(5$B5dj0nqUF(M#iQ;QK1823na&&~FjT~H+=%XO3+>vpVl_r|x7%-pGw5IP zOHK3!o-0ljPPSufsix*~M?MskbPr2di?xREpPXI3v8b!;W+J;1!fmJ7?U4JaauuTX z2}@YoASQ$mA*tMpCpjvbvgkLmB8}POshkNKgv0rf?g3^k$Mo-(<>HZ~kA;joo@vSXSc%WqECT7bHW3zFtah`F$ z5y9T~6YfF6p@Z}&;U4pJEsTqMpQCr~2hbbFox7;h8#(S9wUO{FJ?9~!Li8jWna^s;F^wuxi|evtwVebF2Nz`TDl&rCpkHnjt4JIuD;Cm6XBk8VYaN9nQPo? z#5#d}P$Ow;(M=`ypf9J{rNAfTEFBw< zMhWrxXe{vTQb=8RB5qcAJm}ES$=-Cpc#z&io-!i8=Lq+FtMM6HmtSzdZQ6s@_rykb zitfh&t=vS?_tI!LThi_&X3I|F%f>^-SFnD;tH##|_afnr67D;~`w@OP;cc$Cca2Ak zZyMh+zK!bfj`66m&3MdsoM|wgG@dfP%f=YrN6)?7y{lU%w~^kY8;m$F2YsKBK9sxn zVCvk2qUlAEH+5J(4{@z^;%gD^=b1~-5A5_U&8JY70AU%pTK=oOH|SYUkZ`XM?oIkc zfk%LM2=}%Nzu)Tc9Ai9f{E)T}wEW&6+{<$N5FnY1?$T)d)cBe4bK@6;gWV4k?p4CQ z*6!%XBu9Uxv!hEd-F5A}SNGZrlGnc8(QA*R2(&4WExzM@rdjS|C$gv*;RdR zHL=tQy7~%78=6ZI;3x?xNYOj;euZ*Cwp3GPH!)1b0^E(wjdCBb+)>zJU2f4WO}2Enw1MQ_Bpg1piDmeJ>&MPz zXzFR|C6^)Ii8$7|3{Cw|hNk|e0j7bbV8R_I+zG;+B;2X?GVI(C{}-iZ(o3cGZWpDd zOc6^B4H!zz?bTR2WGr5?F~yi-O>w4p(+JZ@(((ZT5L z4Q#KsQoT0dmgGponxD8YiJorC#zOk09KwC>-k{YqomQKCzaR?Xz95PV(ogIiK3Fcs z5>qM0-%NJGoog|b5$-G6uj!BF>YMCRK2kr%(=f@`RhnkeJ$+kE)pYN0?rZGn+bTxO40`(!KNG(lII}&P@T$$EX|v>T7rJmb_PpqDvpPB4PSZow;dYsJoA#LYn(o7T zb@!VdFrn-A2jTuC++T#dNVvZV_YdLzB|L*BVUOuyx5GW|b~tnj6yo#SM8d0NhvR+z z=WuB54cF>$hp5B7LU^U@aIc|KspGsppb&NqQTRwdQK_VmVADGolZ3k+CA_-Dbd2y` z-E_B8ruQXxdyl#s?+xGa`VQ`<;I8OyXHB07o!7 zTq8jG>G3ynf;kEPW=de;am{OEB_uS?#{e2h9cavBg|uJY_Csy{QlCr3V2%QglHpmXzt_g61-Fx$J@# z!bf#>L31^XWu9f8ZLTrb5?)7mf$(^MH+fvpTp+oiUUtDA?if`%#^v7qMfSdCZ47RC zyn(1NZqOhHvtHc+mr4$3?!p1tFGL5d5FKzP7VJpD?9cFdSczstWS539uQIQOVQy|W z4BS^HK}GI^%+bH*C;zYc`EQz^Hro8)o;_Y}eoms^cx8A^ zr4aTb!k(3Wwl_Z?nm?k=&l$o`XfdB9{KRfHKcAVul$xI}#O7xby?2+P`C&i5V)OHz z`MlKp{2(?zQ?7DJZZ$?g>2x2ao6NsqcGUbk;iqA&sLlKrj$AbVjknIQ*ejg}?ljy( z2WJSMN%-2!oYIJAUJGkcT=LAz7ZN^8?4V!v%xm$n_{vUMKzKweU|bO6n$oz1g@-Madz|u;!AH0I89NU%UezfrgC(cT@4_j&dgjIIm^L`2MQ71l z1gykww3sYri^XCk{0zbu5q>7&iwR#scst=s313F|@;#Pl$tf-IQkTGjX38NuWu>P} zF#CT#`Cs^?B^^F#nLzjow@+FoquTWI*E~ld-qCd0S^VkoNlUgR7d~l0jjC#~phi`9 z&nGQ~mYHxc%M4{J;b*}uTl)nwE9moX(v^JDQf{dfebQ1P`eY4!@=6cM;sBJT)`DSY z8lBO}?Zi>mR!cn{f$I888qMP#gDsXWb>BxUPRqP24f|T=TNa4JzI+4W-;jrWE{16>x1a^N z&2qc(l;uu#813)O7oRzn624iyt>5O_*15xDx!bZ{Zb6n1e(ohL$Y$DtY_V*$+-qqe z{5--hApAnYFY>e?mRltMpD+18W(LGSh{^S69_iy?hsTX;YF03mPCG}7yJ%JvMC|Bn z@A#x)dCKxKZC0MP9JD-RdDilr<$22smKQBA5&k;D!~BHs%Lu=m@GA&^J>gdp{)Rmk ztXM$*SzdEDD{m71M!8v8HrYr5I2d}H}uywzL26L0l5qm6)jBoWn>o0VTIze&vs#*Xj^ zdh1m#$-_*A6ZiVd?$;(f;aeFiD?VLxc*5UE_&eN>7neNYTfMD5vbSv@{GFY>&C0<- zR^A$5)mrgjzn1WK5q=%v@Ai0`sq+)Q+==e|9DmjOwKY_7to2a2RKM`y4attPA4iiacg^Y0-jN`4FBw-Wwd!lQ{m!@g~g)h0QXHBNFYD;^lO%Z|0n z<5>It=UD%RV_C<;v8?HY-{E#F>m*d0;g4IVP>4SYVW;#HW7IbHt;m{frFU#A?%2Cq zthi(E>7Hv@3$65yt!%XxiLSL5eqt?wYw`D8cE=9%`cBTxVXYFq%UUUV*Zo(y>N2mQ zQ;pUJ>m1`LYa^X%lqT;8|0LltPK$A~*DsyDv(B^5m%Zu2Zp%C=~qL?N9^xUtkFIf*!r+S(2FSl4RP;jW5 zPW8I=O}K~k4cZNUg?58`{Dp3?dTAHk;IM=UF&ajmGqfJJo|0Var080&!L@q)MMu?^ zUgnVbWi<|aT~?L*G1YnokEzy=2!BL=OtpSu{+saV^>pzpO1$yw4@Fd~ix`G#e zZ~Z~`!V`pl`w}nwg?izy)(h6(taws}8y_Wn8{v<6?rp~ZvlrUDB`-YQ)xE9bthw6@ zZCYD@c%d!O*2C7**2@-T>uu{}>uW=Q;1uECCH#AYM+fEu!k;GmhlD>v_>cD321s6L z3y}thY+-~yD|;cP3FHByFaGC+|AiOYjPOF6iSQr0z0hX;PhMynVH*W6w2dVEr!BV8 zg#WC2UT90SrHHpSTe5g-`}``NBv+UTw#lON*(Qn3_hmOO$+Aty!=o+RmSfAc;l}$F z;lC#QH-!IoyDi^_;bPki!hc8jpXi7&|BGwHbQSasz!w8N^j0ko#oRP+7{E(7ZLu~7TXfSUl3167?;N!V&s!JCTAlE z;<7EXEhqeMg#QyQo}9``+o~=C6K$)RaNEs<{~dve{2#7ZPbq{Y-0-g00?XImVO!VL z^>^d?4TS%TUVjn$NqY(}EMe1rsR_s4l=#pO3<21x5UcKpTNyHA@p~G`1=zw8tGO_P z@Ow}xs0Vn0mv|TKEQc{--p>@gCU`y2q3K?Z(tWu*d)vZia`y4 zy~E~!CNLM^`Y@~`9EP{x!eHyLO#u0aZ3Vw$=SnO_Fch{N8UzLaq(3wg#DGMQ3{t^3 zkPapS*kUMbF%-5K3R?_?Er!AtLt%@d(0S^(1JbybtxQq zh6e*|HyUmL$TJ-2gwF=hA$%TK02YB80rUvJ6~Lz9>%e*dn}**5TERmAF&?^#pMFsn zJR-wE1c(GW0G%U^0Qp8*K{SX3@n9r?43T32>O^ERKs}5c2hzbrFd3knBBufPc4Q97 z1Nop36oF!32W0>@i>w5&StM*037bX2W|4D1BWMQmzyh!cECJU60+xg8!42Rhuo~P9 zZUwi4JHcJxZmI0@bZr@==6J{0viI0wD~@S&(5!7t!9@F)12VRQ^o0@Qn* zFVKJh&;tYk)H&S%FbE6=sQE`V3GgEUItl&3K!Cgjl%at91mq{690k}{I1XS_;a%`P!x-j)6<{SmnHpAs zqu>lU3m})_Glnt37RCes{f#LAvKhC7hXLdV0FQvjz!L!V#^M8lKp%j-EXd0O`&t%& zMF4qOkQbH^WGo+nkHMz^^~M?xAUlSD80!Rp{H$oBtoMQY0qUp~I@ve?TiRet8|sKH z6hLmq_;^ROn7zfe;@{GS5pxonkg56**x?c(a z-x>jZM)U+In-R!k1o9YxJVqdo5y)f2o8WzL8k_;hZ=?+*f@FZaMk23~cY=FCD?nZ& zk=ID*J&FZNpa$LmHXc<4W&xD{s5zteBahL@ zV>I#@{j<1RHZunLj8OqEfHE9|^v59mF-U(*19%;r0`Gwjz=sSoRsbWwC@=;j0MwDO zEnpki0d_GA4l@a;TM4jN0_>FldnGi3WncwZ2~hS4NH^ge_!@i*zGs+3*eP)emlBn>&v@8pJY*ez8k_-V!6yup zJ`_OSbjX_ydDCOT?O+SI7qo)y;7{y4kGeSlvQL10Ccr)uazH642gq+i6@W|=P**3s z0A2!z7-k~mnK&Fo0X;APl+(mjU=6qh+y)@i#P7fl;79N?c7=!TlaSA(Jdh6x!9H*R zJPn=!$Zs<2IXMi3g9s1_oZvb@z;bXs_y~Lpz6a;QPuTH31xy230C`P8UQPCQTrlMX?y@*FcH9+}KLzzrNnM{KnriFkZ0JfM0 zyHC>r0ibS98wJLKB#;VV-)R#7^q7Y9r=gxqTMVuPD**JG2EC@O0qemo@DO+yJPKf+ zY0m-3Jnbkr4o-p7;3Mz}_zZjv{$Q9)FVGJR1R(%&WlK=#d3IvJQZQ0QSv#1H1*GQx=!_25RZ8r%YI2W!FI0Og*2KY+a1@UiU20A$XF z%-N7R8+vD>9%Z8*WxoPGWtbcV7zR+rImjpH4uETNPJmy)-_o!`F7(NTy>g*TZXW<0 za)UuA2m>ge+z4O;v0wxk4H7^SfF8L>KX(pj0`maMBX=nvU^zhExp#q90K4bz1<)rK zy5v3vo&?Y(_f-J-a?gQp!1v%s@C*12{0Sg;9s?kE9_*gi4-5d1IWGhZ0Yd>~&O=$` zp)B$Y0JhJY1z_7e*fH-oKzh>$0q8S*25^8XFdNi@xd7!eeHlRcOurGJe5Rv5O}`bO zjHYh^Enque0WpTrvP>+z%>QC!C~+YI0m3k!Mgyu6nqV!L&16QGq?bLXP81Y@B#h+ zb*d106~adfO#pT-M4c&21>?bFFcm-AxA0r=J%G%Gkhu^t7eepCzra7z5ZesYqZy+>2|&5e zKt3~$09;cP01O}&zz>R`PZ8`@1YL@z0q9VK%2`wZia;?y`4mB~q6PrHispg^U@?Gh zMVr8Ga6fnmJPP)Mr@%7+x)ni}BIr`|K7cMo(4*)F@DunAK!>7>06NU%Kz|?r6R?69 z5D%c&OvpPEWiS(EFcWgmECe$F^qpA>P?u&_0@S6MwV)n2K@+$gK*pJ{=}g$J82J<@ z09;dyGAeEb_kjn%!vMMz9|S0uVw6iU%B2{(6hjxRvcwdl-W8t$p8@Dqj4~?z4x9(j ztpxTi83^D9B|||3&;yh~i5Wn*66jI_T}n`gN?`kv0sz~WK$jB8RRUc~ssZX#$@O48 zfXz#`fEKVF>;iki{Q&xvK<<)P0DQOvGMBsw-Ue*|x|cxalJ~%Aa0a0M*kKF%7yvuk zR{*4Ehpu+$Q>p<$pf4Bzg26Cg1Qrkt;=o8S8la3y6TuWP4WM3?Lbp=rRyqTq{*ZonSYBP0OKI`2hgE%HbR3FM>k=x|M$hegvqS<$r*S z4C7#d5_kdV=727aeqb2T0Ru1t_=p2#;6NETPzH`kARp9#df)`jU_Mv`mI4A$){Ywh zWOhJi$5zk+Ah!c@JD|G*GCLjs4+GRK$2$PFsOSk`#|q?AaUH-l70{>RV*p>MK;5Z; zFI4;l{$iL)74QarfCF041E7p5|38ZEGFYpET?6oX0ZBm`=?>|ZloXJXkZwM5v+0nO zaFd(v?vju$2}ucQq+3Cdk`~GD^2asj%y{0l?)!P3wNK2PF+G{cN_KLQ2R+()e%q$B zpcU=WtF2ybyJ81zzh^vCa7S(3QCstGD^puN+M0jcE$rt!m$=Fe{@_pk;sLs~mARdJ zYG>x{Ak;+t~2DPb+9fUQe8S;k78}==IkU326FnPlw7{*8 z-Bq|A;hrDvTL>>o3Cf^XxL)C3VgBLv6yBC_%s*V8a9zUtV)o%?A8zj9v-pv9Y-9^R zv6J2G!w$j^BX798;Wu$l;WCHI94>RXJ%qcda5okHJP0}_ATQt03v=k`c^z*BL8qu> zAP2e8r&9rR>GUO)s6usWVn3bSRi~D;rX3yVL>I>3`JLvmkR_~OHEUVV9`vRiGPBi ztLJx(#m9U?Vv>=9RG5EP^Y2=m(v(A=uDW!UsjJy{HT$mS-nBDB7|IAD8OsDFGY#Fk z%G}k=yKX?`# z`IEo6&qLk@L9bZEBLVKHm-+WfNgC3ThZ4x$s}^;rPa~Srf>yL8i~*Q?FE`aI0-1Zs z+$)l?jAs&4SkEcU_S<9>$Me3muW$AFb{|JM!D)WuDtdgY$F~poo2NVvg5DvbVJE#~ z6PHiONm0I_4CVQXs#K>2&1gwydhjjg-g_W}(WSR8z2)w`kWILm-rL#59`weShLGN4dx~ZgLB=@B3dS zJ^DTgf_?#UaWDPce!nbyMo#jOpF-%?Pv(AR-mfO|_NzlZ8X|AM=Ga5O*0`yD=H71+ z=GxDD`+HA+GwAO({dMWDNB_AjU@=QsgAV<-V>kWnrvH9^!94q)q4)f7( zz-G1~^MIZF%w7&4^ME59;{;~^oqPDsY`-(d@4V-`S@_L&`h52;2nI$c79SIjWZ2I@ z`x$6I1MO#^{S3@aUP@A$a#Y|es-VX}&mY*A0Sv4ex_sP>5*6AU5_eNZvv64$4ecWF92*AiW3Wry!qGl)A_{Xa?Rp z$a@BVgx?IVL|c3VgS+Ey2KQz#qtIdScqTEG>DbTUWvpN|dJWcV@Fw&a{NM9$aff^S zjb4NG8vIWX3^D&9F-bxSQlrlhU4~>M2f6UKb%+DPiLB!!7rBBy-`_-+@1OCK ze|gJ?Ac(M^2zL~bfW)|`2)!awVg3O9iO?lN z?ua$)D2y>4x_XwFIWR7rCLuDQs6}uQ36SE&$94jzfRM z^M<;^VfqX!OexCpB^9ZG9>W^bjF#BXu(q_P7k$uc*g%G$+pqDJ?%{F|mwR}9%ze1I z50`m(3tG_znTNZp;hpG$TN=KKlepgzN%6c9&CzGXT$Ztd)!5C5t?Xex2RXtqPGCnP z&TxZ2_!Hem=r-a}5R8n&r=%tw8OerjBXt{@hc75Yb!t%F$I*SH%p=co0k<{spCA}z7Nd$`_oD{kd82e4 zrB9@LicCOa>?Sff8OT9y@==h_v7^Z1RH6!cMb_jSbc^hc=SL1@1d)tq5>uIu9Yn5R z3p@B3eIj*x{T3dOn=w=!4v2 z$nd7(`c-}a7IBpwmY1~b2aR;5o z`NqcSF;0*1_A@>jF^Gkoj89G~(vpEpl%YDcsY?Tz(wzU%njU;h1S1*EI3_a{UB>G& zUheVcJ^l!8X8cLcaE^H@A!9o2!aVRPmp;+bYz|ohj_#%7gaIa3FbIq zGoI%^4JPU{@e3+anQDAZeOl0pwuE6n6FXxk69?j!CJx27F>w^ja5odTv4fx4&q4H> zc$CXr!;MaS%rjo1%S5xEq{pPFBt*7J`Ef6k-2SBE$U4c~CzVI$Nit88d6Jn=GV@7h zK1tq5?Fpw7UFl9QdgG2J$vNo)uY+K68a!`uJBH)$$>cSxXA|}^c{hjAVe$!1bC&bm z;tuzCh+dPQ2Emk1NJV-wk(HeI7N+E*0A=}-TGXQd6uGCE^_1z%VlE3< z%raK6nzd};7v!DtE60#|ip*1fL*^-NYKj|}at*VengX+(YK~JQ@Vu$V(P!GnB;iw1 zlA0{!AwPvEg8fV@iJeTVMh$9Hm-_U?%}g84D8?`m-@>$M_!g%5hNo@fCw5})(++Tu zBbfiR%iKloY43wzx|^9EjTpoxF7Zi3Qa;1nrLXR2$ zJ>QIHJmwj%&})WXGXvbv%!K$BW@aKQ*)jW>GR@Ru=I2zPHf?Y(GsEdjH_UxzZ~CFz zOqpkz`AjpPDeuf#%wazA&RmK;%v{N8%zfrxK`_f)XL;`|@0n!=v;1b3F0=HQb&EUP z;{h+wVYc1Owwu{@GdngPlblrOG&=*C(Q9^j%y_nYncaZKw7_>gTd&#e_!jS;J&Z`k zG6A!nJsn+U%Qbry+c?SzPIHzE$UFNQH<5d`+_PWvjt@aFN9H+EiB2qJp5q4QBp?xP zXwKJkXA0gk=Xwy#^_#i+%q>G@s!@YlG@=!438N!ju%EdD8G`S7?g;dnJBAf(!Hnnr z%w7(17`^5m=PEaN$WzRHt{a-G%UoUNMZx^%$vrO}1t?5WN>GZjd`Ts$P#trhC+|FS zpJ(p#WS%GUJelX|J+CKjYF=O5(LA?3?-Fl=V7~XvuYljoAIWmo;cxDIede3jd|l@M ziVpKn;qTJ?^IXJ!=HKN$k9fj!Uiz0->9N4`7r2=P*~o!?EYNF#UJHs)k;>G=4J~L! zOU!TUZduTo$mHWvpN|YuSKq3uInk<_p}?0(lpl!96W-PYdK-;GP!T z;16yG!9sIim>zRo=)DWQXQ3G^^qYmcEYf39D$%^65>=>%*)Mhvi_LbiIWB${1WP<` zNlEls(vJv+Gm6nn!G4x3z$6;!<+?0ih%U=FAm8#coZ})_kazj-+(z!@ zaxa(r2Xp_y+pheRadQ&R9bb@4alhuL_~4}S*13cp!lPb(@>lW)*x zMFVtM(E%M+bfpL1Vm~W};oeq^W*mC0n2hWL_!rN|{&cy|O<88H~GM zxs#hguqrCvv#J_?vuZqR*vfYFS!G_UbXj#89adf7GS|3){jB<%r@Y`5Z+I63tMypz z`Kxo1hy2*bYQ0wLwYn75sYz4*M;qE>_N!%Dt;cHL#%kZf>WM62IV<^*b!=n{KcU-d znOB?nYPYmn-qn|IPpjS2YI#??r`7hb`W_F0;Kx{G!(4y#-XFc^M>F`*Z+_HejUH<< zl7-L6K|yp_V>fH;W{usf`HCvkrx7}>X+bOWTJt?-yk-j1nZ z=&{B(vBu2TnE9GN&|%Hj+TKiKJ6D5Xo%gJ>%XNOUE{u_w(>h(&>9TGni&%vlTDP7}Y~?2oa)e{} zCf4b-?krFF5CrRe1M6cDn@>o9Uh9*Rnf$n&^~Esv^}4Jtk1p$VSzn*l$i2QF-!Yg7 zhBJyWnE(1oEaeAQvKpD!%e;OgZfX5CcCd@fybgj5X|V4N_PN3HHn_hH`fPAR8(#2= zH@pjijnUC#V?vVfDJij^jcKuyjd{>(VJu%)0rN8OJ97;8zULZEZomV zbKj`XMqM__v~e99*vkoi$GvR4%Y7d4gy;N&ZX0FZ6rV)MyD1sTNrk+dGLVU^d`1P# zd(%j~ca!&QGK0;2vsstTdTega|7b%yx}wA80Sw}MhA{&3+&qn$%t5csdTm~U9-BRX z^KYEz64%jd^DX}5zjvGemXB~lTjHY67G1XJvLyw&Y{`LqTdGihsDxhIs?nJCbi&-X^+1@wqBF^NNb^xBn#WO(;3H?*rTZfKXe@6ukKLZX zyAxgMK_B$mt=I0sjAs(_S;BHwvKE#^InvD>$>`#0`zkB2-Y}#>a|y|y}s$aZ+IUB`{EFvL?k68 zGVRl2pZ)Fgo$o6}E!_P+cfYR@O=&?Z+M?S&nfDFid*t0WoRN%1-hC69jCn-%CX^ZzA8RH7sMFPSM%J4WF>zu4t3esj>baj-DvbWoRrx*V*C z9tRuXh7LBPC9P?TZ{uJu`p}<&3?TwN4toB<4Qyr`yV%V>4&dDfZ}KO9;dT!Ceh-@a zL0t~Ybtndj$x3!|k(UCmrnkHdSgpTh?^!ci`Ah3ovzZSDlYk!ZM=BS}e4D$*+%>C$A^f{`_QC*H6K$oNE z_%Gi}{^czng5a3E$37w^avziXnB2!Qk(JMo`B*OUk{_9m*~KxtI939)Kh_(wJ!X!_ zeh-4GB99FOzy^e2SGrAo=%YVX9CL`S+H_X)XA$bG`x zPni1&b3Y;Ti78A+<`Z+VixYNnVhLt{;${$>G~1Krc+z`LcExW_ZsZJC@Ex4g=j1JP zIr$PDPTJ2&`#BYbX!!edO0QE%(Cbu6(%>68rQ4~}RKxdhst)z>jh<@G|7cAQzGVicHbf*`6=*I{m8H@d#(d*1qHn5um z9O73_a+NQTd3N#3niZ4*e$gZzU*2S-zwaRj5u)zQG;+=8k>~ zrxP;&Ci8DS>5cFDw*d@fHrp}Vvmr9$d1pJL&)L;%W*a-$#X~sF%-yk@b6t{9N8#%~L0Scqnx#F1nId^ofAYjinh_UH6C*Nwr*c5VTSaWCgq zAnUocY(VC7GM|(A+zHJ5+;7Nx?gE#Q_uNhXz#h)s4TAILem)cCdft1_d(Zie_|17; zF6eO~Eg3MY3t7pF4i`#L3cI=RB^CLKx-_6MdR@@#f_u84#|6*7Fo~(mU@r4n#1g#w z!WP`og}vxv9VG_lL_lDasd=p*&`OS*FW+T=q>|ZcaxA z@jb&B$!NwgktyhQS?0?>vJQDKZ^Ha9|Af4k?cuULTt2`-%>7DK%=L=*Uh$qQW^l!C zuIO?_k1Owk;A)6yMCTK9xN0|7?dGc8T+Kul%=2m?iclQAuIhEwp04U~)$^}*qbI!? zfL>Six;m7}Ok*)Wu!=RfqpLDq)#IxDUHz2{_+GC*!uNXhIsfpQcR_G1K(}i$UrSCZ zzG@0W-XI9?!e3=k?O~2Clcm&0Oz97y2*+9j=cclCg}( zey-1BAxl`!N><~3u6zFVD_rMy?(i26(CxZ+-_YeoT-?x&B$)q=)TBk18|Htb0P@|a zOjZuujP2G_BhF#p4#thv3jkEk41UK#dW+^=H zraQc;&&`AQ25z3g-Q2XBn>V?~Lmu;tm%Ivs-#;QIafn9(5|NjZl;uk*QH>hZ;v4=) z7u?YAz3ImwhA@=jOl1*r|Go`3^ZU>2~cTj#ipqrYYDxBlcVy4?CN*V`bt9g9??B?FnshP=0PlMlIX z%YC~t=6?HYWWHUSx->xM+f8YKUEDVN+w<7R?I8Hmd;at-{pmM<>htFWW-^EQEMz4c z*}_lkWHBu0y$Nk?K$!Nwgkts}P7C*8MbHB3*neWJaX9qvChyDD*A3<<83R!Twcf;|# zyY_WgpS#a_7X*I=MCBvmp~qh-NKHC2Vn2W7rw~Ob&KH!X31M`m8$IdE00uIc@yx-z z|60OwRkk8dvv+qkMGdoegwm@pZimp!ED^yeZB54 z#{BOe=M3k#$Te->e)CwD$9g<2Kw-@4adFC{!{Zv%rY;Szo5xKs&&T0(rW-x!jXgb{ z#$tY86>IPfJl?`j?BG}2(qnUfd;@(R>+|?Nk9dOpJu&wupO67J|HREd$w6-NQIO9m zMoHv-BJYzr)I;VcdOwl(NlRMco}Tyyo|yZSB^<_kpL);JLio*7U7k*3K8sk&a@L{4 z)1B;QAHQIpPwnUFc`k7ky`Jjz^mY(D)8m=vKl4pLOGXOPlAcUt!MmU7@vIzQQj2;t z#LS<`|4ja8@;{URnT*edGM!n>WdUaYY#A$9&001f=QCZOnf)_&^y~zu`3IZf6ew^bNu&f zJn!Eb==1M+Ztw?xa+fFQ@$b7J@E?NLQL&%bF-gLwq$CZ#iPsq^jhlI0i#pV&3C+># zb!&Psm|=`$G`hUj<+a(rmg)6!HgO2I|JuF0KE-dy`uY-Ak@>aEuN~0qe|f`yc|Qcf zn?RWZC#qt5*^;QqXQl3%K!%P zJ$k(z!4lT9g`e2TUJjtw+ap}W_xtuQ9%1HhpQFoL_w!bdcOl%*JK5gl#SOnJOi^Tg zSBkR8{7&X~GQVp|3(WkTyzkl)hP>~(;GW*u|GRH7_jemG*LU9g-h1Ac!*AZ}@?MYk zKe7(9dcT>U(c%5C9LH|n|He5kV4m;q;QN06kjFgZMG$;QNLn(HmF)NqKIEq$x_!{) zgDxLxqRR(8KD41d_Vz)C58ct>gTHehCg9#bEMo<$S&LpD1 zWfD`F!CV%wn5ArDD+f5jF-~%p3tZ+Z50EX&$9zIUk|1l8l%zrCC^AQpIZ81~Qi?K^ zqXP0qsY-QfQkyP}V*}nB#e1Tr#c!hO5_K@67=u|woyaV7h`NjwtY$6i`I)`w6!j3l zqF2;={KH#51fghAh(Rp$iWZO5q{Gak<)8?9L@SLv(JE1yYJ5#oI`AEGMvGuL@KbrYRGyiC-Si?H>jb{GQ%s<+8cCnj%$R6$YAoNj)%v8jCKAM2veDoX7(B> zqU#bp8gWTVa#CTA(KBE#(eqJ|&#|BAdPOgVyNTYOPIRRQedv!~(Fb8a(Y-tRTo&PW zqW{2;n0s_xqRSP1Kc~3G9n3uXLmne<^q1Igbh)F;9m5^PNJ27Xj^UPKq`?kiWJLEE z*~pF=#At)r#xTbiC-J(({ltu5I3ux>m@}BoJQlK;Jsjr@ z=eWoQ0=2$Yvk~x;lv1E=lnz5|p2#^bbf4aIi;b!8LBt?&&BR&9Mz-)1JK4=Xe!arKB>i7Hgbe&W``PU5yiuej~#fNpU|;rVfAGmnKV;|JVi zT;1Y&cU-%PdxF!Pa>tiDzTEN6J^l*JJ-*EG*Rp|4$Q<8Y#kY(2KV$as-vprqW}Cnq6ST(j z68Kx3K%WE;dC9-L<$VxJ7y~^LCc=IaCdYmfrXd}<$ctVH3sV%`64uA_6Nb@|F8Cf2 z_Qv0$gahy$C-gTp;cOP*?@mH}66%srriAM;|AhNE$shd5Up(M%p7MfM=$26CL#)+2EXTG5vFbVG;4-!T|} zn-ULaBvYAzPKn)9V&6t$y%O)ij1!;X92dEU?>ezwiEr~f2qg&-omhN~E=kNji7rWW zNs^U<$epAz)u=&j>e7J5G@~VEo}@Q@>5t4wWKJS;5}A|8oMbd^Dv7&Ka)d`gC~17W zCuu|cCg~h@aDYSj29h2_m!#ME9UYS1r%s-jT$^PO2 zx+Z&!J4)t`lD*;$?*jiLC~|+AmM<{RPrdh3@A=d&KlPjB_LDp>dL-8)xgN>OphI#y zNp2^}?Id|)n$dzzbVaA+-(ok(^-4a2rPxFAA6ds{wxU<^ogC!^SGdV7?x0I@U6McH zSrAGgcZyHQKxVR$gWTl9>{EPBF-lScc~jKE-_H~>r;s^?%qjFv(F%J=(Vk%};V^cc z(tA=C!f#T#wUpDC&m#0mXpKhLGDy?r!x0c z+c5W3GN<~Pz3j(LrP4i>U8FjW8KjPl*`_wf)IIRL)b22~KB?aZp)_tkO-$ktm!#;C zMvpZ1lO`KE$VD+qQkrs9pc1X|w0Yl1A<{ zmwAMnN%Ne4c+I;Y5^_3I;0!TI3{90=@zh-AZ7T5dNia7&5<>I8`>jtdYRLkdHSK4d3t%% zM>3Z2OhWJU_K1eO?=lG>(Gj>^r8>_8O-+#V+7MM>x^<|{E40HW*@(B z7<12fg45jQF846^j524GIit)OWzP6tX7``*eGtl&l43Mv5Z;sN2!4~Os=m|b=qvVTPtYGC)->tK%A`w_uh zR`Mh3*ody#w{ezh_=d8-;=gyl4?;OYL?Z?|<}mLZ-k-z!b9ldhe^Dq$CUnn{jRKUy zyK{6#=NxO<#X*kZJILWX$YGW_%rA%DIsUf5(01be}o@<|*Ej^S}4#m`lf8QAtQp_CAZn;_MPO` zFSk3&txxXKxYOJ+<+k74RcSyYn&Q@S{|~)$w<8R>at~%2-ktjbI_LR_c$jM*bIoI} zc~X*ve0+i3bCNThMczD@xr+P9<0kX?+nDDK?}JcY`^xJk^F}8DZX<723Q~x| z6yZy1P@B4#Ti(Vr!<_Q!kynqrdgSei9(nc1t4H3kOkgtRn0GGovERH)S&rG}-N+WU z@e99lj1&CEc`k8G&IzPnUeU?7YH4s!(GX}*j2cJkfkF7}Y` z5&!U-cY*)&GEvbfe|pS6e=lY-Gp#3zVTAUD3CIyDQ*b1?;DQ{S-LPDb8?>zj%pW1zzF( z1?{Jxy%bDHVv^zA1v8Kd?=1KkIkBsP-_QczN5M9OYfl16~ zA$C!48D>;)HEUSM&)7}DW1K|pf@d+Wf_73+=7Rt7U+%X-s8B3qFO-O+$X&>+3Yk?Q zxeLi%CG{MY@_!f&SU@@{5F|Q)B z7V(TC?}Jd$5YdQ1Y}`#zH&Zkl1t?5W^e(D*(Xx1F(HhjIE)8f*Q@S%2eT%xKqCazp zUpdYxbS$b{QC*6@K#pQ^6qBQv9L3DBm^&)wj*6LOvDB2IGBt5O#p=-zJ&U!)d;R;% zLdASL#YW?1icQ4qi`iANMXY8k2ROnp+(C}n=vGp6rkqm+K7z9SO%RB9RvS;l(YRVh0xB~K|kEOiEV zRZ9O-x46SS9`cxHya+<2y|1)6lrDuGmaal|+*N5^OY2(N9!vj^a5~csc}mYfhSD;W zUcqYCvJ*E|`Z#iwmZP*BrG3Mt5jS7sE8k*AD2Wj3%GGb-a2%g9#7H(2Hrzi}QrEMre)ylW$V%a-+9?)w4@`w`JU03PuaOFK%TNcu!=RTV;6@x$_Y+$ zmJ7J2vhJy@dn)^Yzj?~@AXF|E=2Olr%2lK?)u@3?A`g5DYq1P z%E?nso^ty!k8< zd3RLa9hG-S<=fDna5~eCo|s+vzSvv&t3l|?B>4T8{TPAU|8gu7n9NizBjcC%dBhXU z=*yQus6tfivO)q9W0w`|vO;RIk%QdiqadGCly@&1ZtR`DyU@-^R3kA~Q5 z#n!Z=1DzPi5Qbt#70syPJ-oM~_g3`YN>T9cN->FzIaKoAO5R&36In5bO6E|>94g6C z$s8(G!2By!!VW9RQK>!+XoMV<%&Afsc3G(p-!Yg7Mq+-I%&*b}4)Gxfef2SB@Rb>S zWd>i#@|7%KWhWPTDL`S0&;v96N}tMhT3HYOj>1r7v#gwmq$J0)DrduQEBkF_9V(Zg z6lJM~Z=`Z<>Y_(wGp*c|?u=zQ>)6N^eqtZLaG0Z<G$h zN*3~9rd7JyQ?NsHJPf(R86L8c2?~Kr?IGw3Jk{l?E>HE$ zm`8PUs9u_K_y($f#W$Eu^>8}Ui7pIaJa$ywj;hbVjH=63eIZMbueyBIcd>{49OMYc zILR5#VRqFo2cfU+?Q47a+B?5C`>*}}>py}}jU;?YABN!@t1%kiSdEEH#xrXC$zMF+ zZ=Uiz2-S>=t~FEQyQ}HDtC@+cWXC&ex`mo%Q1c7QU=KCTp=Kj`p>NGOEaeAQv4*W| zN6(si*3_@2el_*0sb9^1f>5mhbFXFYwamSiEVUAmmTcs~4r<9!OO9G{)bj3HwJ?iX zt!PUao#{qTzQrtR$yH0PT5{ErtCn1~+(9jOQ0o^Cb2JFm_WauV)z+`JezmJngWA-g zCG82vdun@6Z8NXkpMeY^0=us5UA0$WN3~bu{%V^;?H!m!?O*xton}${1XsApE$;Au zzj=xseUk(4|Hga2@$G%nkM9_acYZSlJNRZ2Ztj~I%;J0ys*@Cb>I}y%)bY>i$XI6{ zi&=)ObyguqU3;i&{&oGXZbovGkAi$oF-lU2DpaQ?-%yVR_!jDpWD%ZQcMa>=g#LBi zLf!ow#4Xf4!#OVUE(q0&P8{5PJ%6j}B_=)D$wPkZtDbwPR}LBKHKIBHqYWL9qh43K zGl)pWG6A!wH;tM2ChPeo>#gKR*0GVz{K}s}sJ=U`AB&IqgoLCd4YJkGL@x4DfWkCH zp88>Qqzkgt@5KnbzrMc-^}V;g`P4U``o5X^+cBs5hxv``+~ozYF{1|ZH28>^#33#z z$V@hJkehrIq!eZGx1vEMs!*L8w8nfIm_-9SYp@hI+`#S{$kafl1~N5}sezp}IKnaP zuEBHUX&4208p_j9o`&f#kA~*ZusB~(2DjMoYs{u$TiVf{4!G@xgNa}`qZq?f+-*a5 z+tA%MG_!__v8RR`kg=hRjqIjTa_ps1YGi2CimsS@qn>z2qXV4AY#W`!-8IgL-8Gi6 zv5bu?QkiO)QRCXwr2+QYxFcQg+{V4=Lw^P`1RWaBWd%FAfIDjZZxCu?K24I70q<>+ z1$W(~1m*aOT6kv@?`-1vO+2^BXw0LD8*Vb5In2k-n%G$rJ8QBM?`!f4cGctvXYl?e zFN09is6@lAn#Le8nQ=2sbKqv0x|ybKrm63}X)#LTR+`r28+_+Y?XPJQn)5%}V3$pG zZ#spwxR<7<_=6|B<_+(IP&4mt=2n`SMKkYhR)nH>Uo&%PW(Liw;#QiOMYB41Z!@>j zY&etgo@P^-&Js4WjUD{VUhKNrA%5jJ*ZG~>+~q!xkgwTu{=tr#N5QO`N5}WxJU)pi zKxy1b^Rl>==H}AeT$;<*++3QQOY>$7U=)$qUGuTbVijxf%{Sk~R<>ha&G)dMv)Ebl z%Ut6ox46SS9`ZM@_%H9CRBQcw{ zWAM(l>(QyLcenkSy&T5-+j@W7Q=CE1w$IVC?Q6`iom*|^o$X?i40~&5Z|yQ+C+%{R zmjdYCPWN^Vkf+@omhuC>r*>=DiY)D9X{UF)TX=7~M?As%+nH~>_d%$=&h2$>FGKrJ zNJ?^2VfO9iXm7^t?Y4b?hBBT>Ol1bMna4s_B1d~U+RM>?JG(yLs$~bC@epvsK8fLu`}jgHX8rgxgQJ{e)-0v%|BI zgWTk!AfHo=l9Z+#<`r&U;pP=?Ug5Qnw_q|dh0nx|h0kXZOL1%At60N& zHn9~m3%Bd=J?!Tob{_8UOSr!;;qE{D9D0Ob;TrZH{*b?U8iYD_V<7g`@q2~^p-wR{ z%T8w5=~GfNi{-39mQJ#C_KkGbwX?hET!!-4Tj$f5VQ25|?A=`&(1vz|;crwI8M?gY zE$@R+*APP(#{}F<*Qr6Mn+)CTvzwWBv(Ik!*-eISTiAvfbTfmVxiI^lCHMk)ditBt z^8|L<(=2+*)2kk>kf)bCy*ltG&v?N<$knF_vi1q56J2?Ntp4AVLVcs~Q4s3ilFs<& z{kzi(&lnJm=)}a04(!4J%zB_%4~z&xgZ$SFNfB(!LzF)`2AQVv$y(7Ls&xnTT5z(Cgp>srgbc&EU!n`Af;@gNANhD*L zz+}unLY@e_k8p1h=Xn!^hRQJ1dxo~fZ-&Y_^f2~5^eh*+#2-B1Z`|5Y^BwvM^Bv~K zhQ%f>@iBv8W-u&2?rB(gDpHxRsYM<18m7lEJ%*X}uzq}pnGPF<9>YeX$FMobHf$%m z*~c%)I_xMXka?KQ!(<+IpGQ1KUjJUI&@j6k_Fvw2d9HkDSI#<}jZ{EM*(=M()BrMamp0bEM3XdPg4PByK9w&5w?UI~e^9-ZOeG zelz-J5E>H@i;vM~jCqaGWlTnN81or9$wNNApbX{lU5wFdjC&em{$t$Cn0|c6V1_Xg zy~d1THuG4;IySNeUB>7#W)J(2d(3s7;$FtQ;tlVE(AW^sh(T=Pk`8&tX2w1F_fdt$ z$~;!)v3id!$mh7Jv32Q*I~cni?-}JnMP+qv;R0U&Z%I!~Vyd0k z3n~#66a@uAK*Y42-g`AoV~VLpW2yyFLBxWH1raNPg1rlBY^kQ2n5L#%&y#a*PR4k~ zzHxouobR0LA7kGvsLvJXYivX0KeiufWH5-ExEXzoy@SVjikFf5*tZyoUdHNW>=@)f zR^4M4V2{VHXA^dR><)JFG5h$0&pCp6$NtIRsClfK$J(iJY93dMx|qc{*^f))VMbGo z^Tz!XgvRSJ+WM?8IzdzN~$EH!7TIZMr1 z`p&XbS#~PREV5*uHJ56R2B8V=na~5zOc>4-W>JKGCdg}oUM5tbhY1_l%r?wt!l&4` z319Io`kL@#5XzQ+_N81&0~&J;=8>(h?6$Wh zXJ;{y9P*gPObS`SN-B|iwwklmoUP_;HD{|idndcGM-wmNT5iNW6U}j=XC|7_q!8zF z0rj{9y-aFOEA%j_1D%MXH+`^2lTy&vqyfl((onnylV0TwMlzcB(bpt>Ofr{AB`jho z<*Y&*U&;g_E4B=0=V=Rz9b+&uHiYe_pg(1|D#$Ur}N`pMHzp8NeRs*t}$ z70T03o;l>%**trdrpce@w zBJ&xyBKH|`pP}X%YM!Cy8ET%P<{3|7r)GF3X3V38V?k)9duH~;Gc(O-W*&vi!8 z0eYFansw-5<`%Y7&1Zbc*L;V*W*!bg1@bSb&s8*}3C(GVz6#nQ_kuW58OU|qh+Ycx zQg9b`s6gEXukaD$n1J`VAeX63r-0eaWfkfzSc}{X)LfwE0yP)tyI>c4uu}zp1ff}% z(v4ei&n$DC<(XOE2cg0`T*$@fr%+yndMRv;9ttDrOc%OhK85B|*q2Q7Q+PACA>+b( zd4Pu)!Z7Skp?(VWQ>dRp{S@k_P(OwGDJ*6oi&0mhUJAFd1N{{4W-kZ$lrK2QsUS34 z_Os)0?`-$XHv8G0nf+T3D$-Zc6geMZ_+WRB6BLzSCPJo z%&KT8-hrZbc#jVm&jj>Ul*1gBQ9&hZ&`Z%~^irgkqR%;uy5|JcqAurfJ{NHbmvJTX zpA$(ZqEPc3HP2D=95v5T^PE0-N9Ne0Ij=F34Y+4+Jv=k_dY<7WhVwdaqL;Z@OhgZJ zy&H3eVC59gK!aV2Q!OP_1-g)ksFQfUMnQun(pTu0|zsM`R$|%NQHuJNY%oL_F zj|G&Xulf3#zk+>y%a8obZ~VdE=xhFoAXI!VS76tQn-GCsirb)k;V)m*IRVl@}5xp+F}S-hHqL1;m3TH>AsgYnFQMeO2J zycY|;;v4j`;7|TR4+~BQp^^}_FrSjMs7E98Q_=$OMo9-c5=9sK(hoaSqMs7|l<22K zKPCDp(NBqfN?u|(ucNLKy_8HM2mO?oW62C=F&poFiQnInEy#Z11-N&idlnAEGYh>- z3-z_od=?(!F#1}kuZ8+4)laERO7&8DF6VO<=2U7SE*T*CNhYdxP{xfhx^c1 z>B9`gK9!E-JwC*2O7&8zm(pDFP-bDdn)VxT| zi`2YG--|Bd66)i(X;CK6F#-21GW*4zS$qwBNFxLNESA?|y)1qJJuH3<@5bV%c^30o z{01W!g}qyB?-qZAJ{CKFaV2Y5k9jQKMm0P6@9uBV%i?4F&2dfzp(T1*qOK)+S#l0n z(t_^vpce_qen~Q^3_yQN)V)OROYGAUH7|LBr?68?)V#z_EqRewcoo?%DMz+T&3&nR zmdatNXO`+`sa}>A;md>DVJl9mNlda zQAE>?81%MGZ_D(yOmEBj(I53JGlOL#nTvauxo7zmcxL&n48uH@kH9>Zk7gYDTRxTP z6fm1PEW?bJuS8$V^|gFGU-KJ(U?$7WWcisORAwe+`YNl-Wkk@5wsb%*WnIuqnO@3L zxDj=iJ%-&WvpZ$>uWTr0P-X^Yukj{!vTPDLOhL_MYA#cAnVQSgTsEHt*rT$ag3yYK z=!|<-yo6^~tm1RN$NRtHXMRO5wKc5R}Kx3NG9DS9yLH_0Tsr+Vc<4*45 zK^{S0<@zW$m-6@ckg;Sl8GV$isoegQmm}wLIhSu>D?8Z9ZVn>*@^3j5geqDf(+ZhZ zbVa5W@~SY`3OQAnYlX8bWK<*#a$IEaaV=AD%@4E8JSg7vx|>|&`Psh>HL+q z^DgRJc{m8IvZt%eb5$(;NoOF}A?H=HSS5>9vRL&5gL#%A4C7^9fJN_SN1uhRQiDbq@s zR{q9GPH{R2RhfU)Ih@Z$TucP*>4-e4qUnx)s`OE%j;e8}qe>lBa<7_!da8<;hs>*% zP=VipD)+6fg?m=JXZ0o2$9}Dj#LliZ*VWyS^XfR_89*l2a}&34J9lvpZ!?|E=xvR& z*Qj?*FJ!tVkz|~)=2q_Db>z85-D}jnM!jp)x@H%9*w3eY!B^P7HHSFNFC5`_{^DOw zawZ6^Jsa~}E4Q`sTHAyFaX0tj&b4w|E4Q_BS?jlD?IwQaPyPu)>n@`)&FGIETX!Ra z8OF;@#mv{)?R6WeVRsN(e>K-&pVs@g>)&7mC6wXL^`G!f5ZX|Sb7_m5H^_NI1_K$y zojk(hJjF9S&kMYX+&8?#dwj@P#cb34Ls-hupVZOIKpBD_iumr9Y{-cgro<*)6wWZ?_EPEk-h$_xXsi*oiIEn87R# z^50#*BDXC^IUR(yhN#V1oXh!KMFSeqlsnPi*2j5*r?7Wh-M7_!TkY^xJG^xgxww0) zcW|p2Z(T|mc5Q1VYgo@F}DI&d%U-X`O1&tl%&=CT|+ zw9Osc+_BA!x9e-W*>11H*~B5o?Q-0n!64p7?c1}+W-`@$hMn6kv+dsmp&eJ!0=4XD zM1VjJjYPp;zPVgJMG3!Iqu9Mk0R!=fKryQoE6A<=VsKuQ|-H6Vico! z4`=S~N?($Y;cgl3*2~AWsf+wS*2~BC_~UIj=VR~3$Gd~j9y#tAkDB(_r9JA}Q@|_= zQQMxSEJICu)U-!Udt|ytU3=8EXFmt{1be>cM}Fovj`1hz*;@y7?7fl>*!R8HqW--x z^rSa-aIaqWrjUkA_u9j~5AraNVlVa%=2?a?4B70pCwuj@SFU^2zIP3KP|v;)mlH`c zc6{G0+=cnNb5 zs)NuGbstgp5zil)NDj_8GL4xOG6&E59(?GC=Z{pe7H1sU%vO#Bp`(`}Ki_K)9eoBh z9(|LyvFAr8;QXU%I$DBx95s)lt60qrcCwqj9N<&Fou0zKsGX>8cpTR7On1{2Dm$IIXY+*Y!$mF<8j?3h@ zOpbrSL4FTHC+c!FcI!j}8QhP1PmEwJcH)GcIAJGF$p6Gb7PE{MtfUI}oN&(x_nh!s zaNswlzE&ok5f@Z)14ml zA|7X*lKUwco+?3Ir_^<7EgRU3eLM9zhf&WdJ8?=)r{!?^QZC0noNkC+INgj$I?@Su zpSGu`Gw@!Yz5(~1zLh(;oBL45Y4bZhgkikIa9+a>oHoWK-uwMk1d&<1m{#lgPy#b<|$ROzOC+&O+Q*$6V@s z!QVl+?ji$=F_9U_wxRkOdcNU&%(tN$8?NQMAl#@fm(dwDHA*0nWKv1zP9EcNWZuYZ z8_A>5c&0IvLfp~F9gRv*YojXGu%1n9VLLV0uSUm$aASQm_AWGbZ{tkd)A$A6)>vCHn7=6RgibOZA~wv9+z@CSJ4o4HZ`ZFcChIKJdC=VK8gF9nqAXTe83pw z)HEA8G~K~3IKSD&sI{4$Xx5xobRv#;`qGcdvn%jlu_N}>nYhI1rZSI`r-*Skb`IZ09kw=SjX-^E- zaU(Z#8+URK_hYUt9_0z-?Yn*97DKQjEyj|?L~_Vu8tQ7Ht`_QQp{^Dsl(Lvj$gX8m z+99KsPh$sL7O|Wfz7N8!%&e7}wQ5FlTG1ADw=%O<{qcOOLEM0Mx|Nz+*^gFF;@nox zA>&puZuJ`OX*GgzS?W>*6L}kp4PKifL&_s?$%YTMGdVtvz7gP$`^cv`&*ynOb~7prVb5gjU3xV zqLwz@aetc>(vVM^+qjc^kWU-)^i9BU8}n&XiN4!>&%Z&q?S(|3x3=PIr z_U6?7VID(&?FTc0Q8=sp2k5oEUfWM$7Dc$Dy*akG+wB*#nssbs3uf5!))s)YaK6IuAzXorf@t zmwA;pcndXm&SfgoDPT5pk$vZtRI!!~Y-TI_`IImCia&#JRG2!bGfJINmm%vYSx2>| z9WswnW0V@B5=iC-ZsHbh<6&N6IIpA5D0N23HcGa>yBCfc#{`O)M=@p-<-Lhof}M%7 zGf@>(vKqBUoeIL&Hlr^O;k;|j;@TR1;~!3NItX_OIEPEnOP4EYKx3NHflgdYSLENN z2RHKokMabAd7h!Xh#7Qwmx)XvpBc#AxAMYW=3_^?tl~?)<~x4iCw}E9zw=iRj+S-w zg=PMlhBv)Eb?G8l&eT?`XM2 z%Q@QqM%#^OyAi#W{iriqozd!y{)4|cj{LjIwQDWxbl0nBh)lc6w5xsTYG1mxqAlw0 zs{XE>$v~c6$FPWfIIo*|c8ljO>`u4GcoMmHv-92FKrh`!@h%_m5wh==kL{l37>Ni`FA_SVSdJrbU&L5sK=#T$<;KX36b>SJ|5%|)Ye^X-Jj+;hM>moYU-}9 z?&Ha3GV1HDuI_fByS?tdgyod8k}YhfhTZ(YpZvpr_1WPV8ONwC=5k~mBkPzp$Tdc; zG4>*+J4x7ym{iia4SO2%D)NhwUyS@>x8Ldl4(oST)D0IabZFEm3orzBC$7kb%zajsgA!>6L=W+oTA^)Csqh|yyXiZ!6(enmw;dbugejY?$ zJ?%};7a7TWe8^bz(sL4e>8Y2V^D%>-_M@j6^jymZs!?N4HTFCbgySxzK38xxjcCd> zs4GrgadE`cmww1OE}a{>lY3BO+(SHy?Bj+ZpE!FHXK&)v8K=&;EGANbor#lioQ&h_ za@;CbvyLs;k+=hVhJ53G;&c%1CDUFq?IqJ*=OWWy=F-cq^s+0xuA)61>CCm*m0tF{ zS1kJJ)f>ChD-regdX1ULsF!?tJFj;auE!4bwmZFt^Ez)L``&u#t(V?8eAE%Ij(GRSSF(onY+?)YjhAiwmwe43^d7Ii_}_xCZy<(!?=YO8mV{QcMI8z1 z@a@BJf@~7J2MM=uJ9nX`ga=Sp!lS4y;SEMGig)>dZ1Ry;!YsUR3G=WE3FXKuVKwWp z0}0>rBR}(BZ6`Ssg!_c4!zEnCmB_D8Ga^xIpKCGyK7F{6o4JiUxrh5vZy)vcd4j>1 zai6zQbDzaqwFd66d`!)zC*CGP%Uvea!u}jH4(Mz&klGDgw5Z9x( zF5htXT|lMLp4oS!_E=@c-Bc`QJ0$?i_pOR_m6n?bS}B!9|5zD6&}hcJs2nWtQh zol9xTHMB(jDQfoJ#BfSq`q7_s>`TgZ$UfzM9^z4+K#eJOC*@V%U<9Mc!p@|aL5km) zl(`h6-W0P)u}3NPD8(M7*rOD+r+khXq^LPXmMKSraR1tz#kpKSJuc;PuEOs0Z-Sla zA5Ax6=s_>MSN#*wPk;UNmwkU3_aBLx`ftZQsd7p6OzN!+Loca%N!3g0XvUF?Iiya< z98za92Ycnais4jym1-8LW|6uceWco(R6CRUH^(^>gww+4E3Gb<(HPmMb;7Qsbww?{ ztr$*=rw@a;jr);*+M~!n&HkmSH|=Gnkk1TeQG`87vnOeCPm_DvX0}nyF6>L1eMz(T zX@~iRBm9niN&6=Vr`O?Z&f`KFpyu>uG^aCNkbQbA$)qxXOm5;n9zgc#YEK`^Xx`@| z4X{hc49cgJCR|Bd^<6mk%m4pp65kg;Wb8JuQK$N z@g6zMWLN6J1B||S6ddb+qr+mvH4)Y5~_?MHYd7zycSckJv^T4Z7??CkpOhvB) z9%{nuM zLAW#1otf^;bZ6${xFd52!+4oDd7DwZ%lnvh=2Ye(m&~P Date: Wed, 16 Aug 2023 03:10:24 +0900 Subject: [PATCH 23/55] =?UTF-8?q?docs(git):=20.gitignore=20=F0=9F=93=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f031450..ed7c9da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,101 @@ +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Xcode ### + +## Xcode 8 and earlier + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings + .DS_Store Box42/.DS_Store -Box42.xcodeproj/xcuserdata/ - .prettierrc .swift-format \ No newline at end of file From d1ce1c900b45f2d5ad27528f79e78b9bc69429f2 Mon Sep 17 00:00:00 2001 From: Dasol Kim Date: Wed, 16 Aug 2023 16:41:06 +0900 Subject: [PATCH 24/55] =?UTF-8?q?feat:SPM=EC=9C=BC=EB=A1=9C=20SnapKit?= =?UTF-8?q?=EC=9D=84=20=EC=84=A4=EC=B9=98=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 29 +++++++++- .../xcshareddata/swiftpm/Package.resolved | 16 ++++++ .../UserInterfaceState.xcuserstate | Bin 0 -> 55554 bytes Box42/Box/BoxButtonViewGroup.swift | 53 +++++++++++++----- Box42/Main/BoxViewController.swift | 4 +- Box42/Menubar/MenubarViewController.swift | 2 - Box42/Resources/Main.storyboard | 49 ---------------- Box42/System/EventMonitor.swift | 2 +- Box42/Window/BoxWindowController.swift | 2 +- 9 files changed, 87 insertions(+), 70 deletions(-) create mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Box42.xcodeproj/project.xcworkspace/xcuserdata/daskim.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 10e6af2..5ad7d15 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -3,10 +3,11 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ + D676A64A2A8C5CEA00B5C319 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = D676A6492A8C5CEA00B5C319 /* SnapKit */; }; DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */; }; DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */; }; DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */; }; @@ -97,6 +98,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D676A64A2A8C5CEA00B5C319 /* SnapKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -295,6 +297,9 @@ dependencies = ( ); name = Box42; + packageProductDependencies = ( + D676A6492A8C5CEA00B5C319 /* SnapKit */, + ); productName = Box42; productReference = DE018BAF2A5099F900FF0AA3 /* Box42.app */; productType = "com.apple.product-type.application"; @@ -322,6 +327,9 @@ Base, ); mainGroup = DE018BA62A5099F900FF0AA3; + packageReferences = ( + D676A6482A8C5CEA00B5C319 /* XCRemoteSwiftPackageReference "SnapKit" */, + ); productRefGroup = DE018BB02A5099F900FF0AA3 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -568,6 +576,25 @@ }; /* End XCConfigurationList section */ +/* Begin XCRemoteSwiftPackageReference section */ + D676A6482A8C5CEA00B5C319 /* XCRemoteSwiftPackageReference "SnapKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SnapKit/SnapKit.git"; + requirement = { + kind = exactVersion; + version = 5.6.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + D676A6492A8C5CEA00B5C319 /* SnapKit */ = { + isa = XCSwiftPackageProductDependency; + package = D676A6482A8C5CEA00B5C319 /* XCRemoteSwiftPackageReference "SnapKit" */; + productName = SnapKit; + }; +/* End XCSwiftPackageProductDependency section */ + /* Begin XCVersionGroup section */ DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */ = { isa = XCVersionGroup; diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..19d4e8c --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "SnapKit", + "repositoryURL": "https://github.com/SnapKit/SnapKit.git", + "state": { + "branch": null, + "revision": "f222cbdf325885926566172f6f5f06af95473158", + "version": "5.6.0" + } + } + ] + }, + "version": 1 +} diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/daskim.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/daskim.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..8f509221410845e00fc7a5e97c7a24001c6d86c7 GIT binary patch literal 55554 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 - @@ -173,53 +172,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Box42/System/EventMonitor.swift b/Box42/System/EventMonitor.swift index 81234df..ecc7f8d 100644 --- a/Box42/System/EventMonitor.swift +++ b/Box42/System/EventMonitor.swift @@ -11,7 +11,7 @@ class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask private let handler: (NSEvent?) -> Void - + init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { self.mask = mask self.handler = handler diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index db80f60..acae3b9 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -8,13 +8,13 @@ import Cocoa class BoxWindowController: NSWindowController { - override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect let styleMask: NSWindow.StyleMask = [.titled, .closable, .resizable, .miniaturizable] let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) windowInstance.title = "Box" windowInstance.styleMask.insert(.resizable) + windowInstance.backgroundColor = NSColor.red let boxViewController = BoxViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController From bb39daee91fbed668f952117441f6753b97064a2 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:36:54 +0900 Subject: [PATCH 25/55] =?UTF-8?q?refactor(webview):=20webview=EB=A5=BC=20c?= =?UTF-8?q?ontentGroup=EC=9C=BC=EB=A1=9C=20=EC=9D=BC=EC=9E=84=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.=20-=20clickBtn=EB=A1=9C=EC=A7=81=EB=A7=8C?= =?UTF-8?q?=20BoxBaseContainerViewController=EC=97=90=EC=84=9C=20=EA=B0=96?= =?UTF-8?q?=EA=B3=A0=20=EC=9E=88=EC=9D=8C=EC=9C=BC=EB=A1=9C=EC=8D=A8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=EC=84=B1=EC=9D=84=20Vie?= =?UTF-8?q?w=EB=93=A4=EC=97=90=EA=B2=8C=20=EB=A7=A1=EA=B2=BC=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 13 +- Box42/Box/BoxButtonViewGroup.swift | 149 +++++++----------- Box42/Box/BoxContentsViewGroup.swift | 35 +++- Box42/Resources/AppDelegate.swift | 1 - Box42/Resources/Info.plist | 8 +- Box42/Shared/Constants.swift | 13 ++ 6 files changed, 111 insertions(+), 108 deletions(-) create mode 100644 Box42/Shared/Constants.swift diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index ceff194..dd38da3 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -21,7 +21,6 @@ class BoxBaseContainerViewController: NSViewController { func BoxButtonViewGroupInit() -> BoxButtonViewGroup { let buttonGroup = BoxButtonViewGroup { sender in - // 버튼을 클릭할 때 실행할 코드 self.clickBtn(sender: sender) } view.addSubview(buttonGroup) @@ -31,9 +30,8 @@ class BoxBaseContainerViewController: NSViewController { func clickBtn(sender: NSButton) { guard let clickCount = NSApp.currentEvent?.clickCount else { return } if sender.title == "Preferences" { -// boxView.contentGroup.subviews.removeAll() -// boxView.contentGroup.addSubview(preferencesVC.view) -// preferencesVC.viewDidAppear() + contentGroup.removeAllSubviews() + contentGroup.showPreferences() return } if clickCount == 2 { @@ -44,11 +42,8 @@ class BoxBaseContainerViewController: NSViewController { // WebViewList.shared.list[sender.title]!.load(rqURL) print("Triple Click") } else if clickCount < 2 { -// boxView.contentGroup.subviews.removeAll() -// boxView.contentGroup.addSubview(WebViewList.shared.list[sender.title]!) - WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true - WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true - WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() + contentGroup.removeAllSubviews() + contentGroup.showWebviews(sender) } } diff --git a/Box42/Box/BoxButtonViewGroup.swift b/Box42/Box/BoxButtonViewGroup.swift index e71a3f8..0859e19 100644 --- a/Box42/Box/BoxButtonViewGroup.swift +++ b/Box42/Box/BoxButtonViewGroup.swift @@ -6,6 +6,7 @@ // import Cocoa +import SnapKit class BoxButtonViewGroup: NSView { var boxVM: WebViewModel! = WebViewModel() @@ -13,12 +14,11 @@ class BoxButtonViewGroup: NSView { 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) - -// self.wantsLayer = true setupButtons() divide() } @@ -32,112 +32,77 @@ class BoxButtonViewGroup: NSView { } private func setupButtons() { - createHomeButton() + for subview in self.subviews { + subview.removeFromSuperview() + } + for (name, _) in boxVM.webViewURL.URLstring { self.createButton(name) } + createLoginInfo() preferencesButton() createQuitButton() createPinButton() } + func createLoginInfo() { + + } + @objc private func clickBtn(sender: NSButton) { - clickAction?(sender) // 클로저 실행 + clickAction?(sender) } private func createButton(_ title: String) { - let button = NSButton() - - button.title = title - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false + 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:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - super.addSubview(button) - - NSLayoutConstraint.activate([ - button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), - // 이전 버튼의 bottom anchor와 연결 - button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), - button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), - button.heightAnchor.constraint(equalToConstant: 30) - ]) - - lastAddedButton = button - } - -// func createHomeButton() { -// let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) -// -// button.translatesAutoresizingMaskIntoConstraints = false -// button.isBordered = false -// button.imagePosition = .imageOnly -// -// super.addSubview(button) -// -// NSLayoutConstraint.activate([ -// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), -// // 이전 버튼의 bottom anchor와 연결 -// button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), -// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), -// button.heightAnchor.constraint(equalToConstant: 30) -// ]) -// -// lastAddedButton = button -// } - - func createHomeButton() { - let button = NSButton(title: "home", image: NSImage(imageLiteralResourceName: "42box_logo"), target: self, action: #selector(clickBtn(sender:))) - super.addSubview(button) + let fontSize: CGFloat = 16.0 + button.font = NSFont.systemFont(ofSize: fontSize) + button.setButtonType(.momentaryLight) button.translatesAutoresizingMaskIntoConstraints = false - button.isBordered = false - button.imagePosition = .imageOnly - - -// NSLayoutConstraint.activate([ -// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), -// button.topAnchor.constraint(equalTo: self.topAnchor, constant: 0), -// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), -//// button.heightAnchor.constraint(equalToConstant: 30) -// ]) - NSLayoutConstraint.activate([ - button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), // 좌측 간격을 100에서 20으로 변경 - button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), // 우측 간격을 80에서 20으로 변경 - button.heightAnchor.constraint(equalToConstant: 30) - ]) - - lastAddedButton = nil // home 버튼 이후의 버튼들이 상단에 연결되지 않도록 설정 + 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 } - -// func createQuitButton() { -// let button = NSButton() -// button.title = "Quit Box" -// button.setButtonType(.momentaryLight) -// -// button.translatesAutoresizingMaskIntoConstraints = false -// button.action = #selector(NSApplication.terminate(_:)) -// button.isBordered = true -// button.bezelStyle = .roundRect -// button.showsBorderOnlyWhileMouseInside = true -// -// self.addSubview(button) -// -// button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true -// button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true -// button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true -// } - func createQuitButton() { let button = NSButton() button.title = "Quit Box" @@ -151,16 +116,14 @@ class BoxButtonViewGroup: NSView { self.addSubview(button) - NSLayoutConstraint.activate([ - button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), - button.topAnchor.constraint(equalTo: lastAddedButton?.bottomAnchor ?? self.topAnchor, constant: 10), // 이 부분 수정 - button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), - button.heightAnchor.constraint(equalToConstant: 30) - ]) + button.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(20) + make.trailing.equalToSuperview().offset(-20) + make.bottom.equalToSuperview() + } lastAddedButton = button // 이 부분 추가 } - func createPinButton() { let button = NSButton() diff --git a/Box42/Box/BoxContentsViewGroup.swift b/Box42/Box/BoxContentsViewGroup.swift index ed20f4a..78c9b96 100644 --- a/Box42/Box/BoxContentsViewGroup.swift +++ b/Box42/Box/BoxContentsViewGroup.swift @@ -11,6 +11,7 @@ import WebKit class BoxContentsViewGroup: NSView { var webVC: WebViewController? var webView: WKWebView! + var preferencesVC = PreferencesViewController() init() { let webVC = WebViewController(nibName: nil, bundle: nil) @@ -28,8 +29,40 @@ class BoxContentsViewGroup: NSView { override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) - // Drawing code here. } + + func removeAllSubviews() { + for subview in self.subviews { + subview.removeFromSuperview() + } + } + + func showPreferences() { + self.addSubview(preferencesVC.view) + preferencesVC.viewDidAppear() + } + + func showWebviews(_ sender: NSButton) { + guard let currentWebview = WebViewList.shared.list[sender.title] else { + print("No WebView found for title: \(sender.title)") + return + } + + currentWebview.frame = self.bounds // WebView의 크기 및 위치 설정 + self.addSubview(currentWebview) + + // WebView 설정 + currentWebview.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true + currentWebview.configuration.preferences.javaScriptEnabled = true + + // WebView 내용 로드 확인 (옵셔널) + if currentWebview.url == nil { + print("WebView for \(sender.title) has no content loaded.") + } + + currentWebview.viewDidMoveToSuperview() + } + } diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index e3ea76a..26df5dd 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -12,7 +12,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { var menubarController = MenubarViewController() lazy var storage = Storage() - func applicationWillFinishLaunching(_ notification: Notification) { menubarController.menubarViewControllerInit() } diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist index 6529386..b61be39 100644 --- a/Box42/Resources/Info.plist +++ b/Box42/Resources/Info.plist @@ -2,8 +2,6 @@ - LSUIElement - CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -24,6 +22,8 @@ 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + NSMainStoryboardFile Main NSPrincipalClass @@ -39,10 +39,10 @@ UISceneClassName - UISceneDelegateClassName - UISceneConfigurationName + UISceneDelegateClassName + UISceneStoryboardFile diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift new file mode 100644 index 0000000..3e4ff73 --- /dev/null +++ b/Box42/Shared/Constants.swift @@ -0,0 +1,13 @@ +// +// Constants.swift +// Box42 +// +// 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/" + } +} From 1b6b6fc7f4fde39719f3ff7b8f0c30a556392927 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:38:50 +0900 Subject: [PATCH 26/55] =?UTF-8?q?refactor(webview):=20MVVM=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.=20-=20url=20view=20model=EC=9D=84=20=EB=B0=94?= =?UTF-8?q?=EC=9D=B8=EB=94=A9=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/WebViewController.swift | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 51028b9..55991ed 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -7,16 +7,21 @@ import Cocoa import WebKit +import Combine class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { var URLVM = WebViewModel() var webView: WKWebView! + // Cancellables array to manage the bindings + var cancellables: Set = [] + override func loadView() { self.webView = addWebView() self.view = webView loadWebViewInit() webViewInit() +// bindViewModel() } func loadWebViewInit() { @@ -24,21 +29,27 @@ class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, for (key, value) in URLVM.URLdict { let wkWebView = addWebView() WebViewList.shared.list[key] = wkWebView - let rqURL = URLRequest(url:value) DispatchQueue.main.async { - wkWebView.load(rqURL) + wkWebView.load(self.URLVM.requestURL(value)) } } } func webViewInit() { - let request = URLRequest(url: URLVM.URLdict["home"]!) -// let request = URLRequest(url: URL(fileURLWithPath: "https://github.com/CHANhihi")) DispatchQueue.main.async { - self.webView.load(request) + self.webView.load(self.URLVM.requestURL(self.URLVM.safeURL())) } } + func bindViewModel() { + // Whenever URLdict changes, it will call loadWebViewInit + URLVM.$URLdict + .sink { [weak self] _ in + self?.loadWebViewInit() + } + .store(in: &cancellables) + } + func addWebView() -> WKWebView { let preferences = WKPreferences() preferences.javaScriptEnabled = true From 4ea7f5aa61404b4e023d29dd6484ce7d9ddcd03b Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:39:45 +0900 Subject: [PATCH 27/55] =?UTF-8?q?feat(webview):=20ViewModel=EC=9D=98=20CRU?= =?UTF-8?q?D=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EA=B5=AC=ED=98=84=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/WebViewModel.swift | 72 +++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/Box42/WebView/WebViewModel.swift b/Box42/WebView/WebViewModel.swift index b3f64ad..2e091a0 100644 --- a/Box42/WebView/WebViewModel.swift +++ b/Box42/WebView/WebViewModel.swift @@ -5,38 +5,70 @@ // Created by Chan on 2023/03/19. // +import Combine import WebKit -// Singleton -class WebViewList { - static let shared = WebViewList() +typealias URLMapping = [String: URL] - var list: [String : WKWebView]! - - private init() { - list = [:] - } -} - -// CRUD 4가지 형태의 데이터 가공 create, read, update, delete +// WebView 관련 CRUD 4가지 형태의 데이터 가공 create, read, update, delete class WebViewModel: ObservableObject { - var webViewURL: URLModels - @Published var URLdict: [String: URL] - + @Published var webViewURL: URLModels + @Published var URLdict: URLMapping + private var cancellables = Set() + init() { - self.webViewURL = URLModels(info: [URLModel(name: "home", url: "https://42box.github.io/front-end/")]) - self.URLdict = [String: URL]() + self.webViewURL = URLModels(info: [URLModel(name: Constants.url.InitialName, url: Constants.url.InitialPage)]) + self.URLdict = URLMapping() + + $webViewURL.sink { (WVURL) in + self.setUpURLdict() + }.store(in: &cancellables) } func setUpURLdict() { -// for urlModel in webViewURL.info { -// URLdict[urlModel.name] = URL(string: urlModel.url) -// } for urlModel in webViewURL.URLstring { - URLdict[urlModel.0] = URL(string: urlModel.1) + URLdict[urlModel.name] = URL(string: urlModel.url) + } + } + + // Create + func createURL(_ name: String, _ url: String) { + let newURL = URLModel(name: name, url: url) + self.webViewURL.info.append(newURL) + } + + // Read + func readURLString(_ index: Int) -> URLModel { + return webViewURL.info[index] + } + + func readURL(_ index: Int) -> URL { + 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)! + } + + func requestURL(_ url: URL) -> URLRequest { + return URLRequest(url: url) + } + + // Update + func updateURL(_ id: UUID, _ name: String, _ url: String) { + if let selectedIndex = webViewURL.info.firstIndex(where: { user in user.id == id }) { + webViewURL.info[selectedIndex].name = name + webViewURL.info[selectedIndex].url = url } } + // Delete + func deleteURL(id: UUID) { + if let selectedIndex = webViewURL.info.firstIndex(where: { user in user.id == id }) { + cancellables.removeAll() + webViewURL.info.remove(at: selectedIndex) + } + } } From fa333ebeb40ca4ad34c9b1d77bca889546b735bc Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:41:12 +0900 Subject: [PATCH 28/55] =?UTF-8?q?refactor(webview):=20url=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=EC=9D=84=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/URL/URLModel.swift | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift index 9763fce..d27e9e3 100644 --- a/Box42/WebView/URL/URLModel.swift +++ b/Box42/WebView/URL/URLModel.swift @@ -7,6 +7,8 @@ import Foundation +typealias nameUrl = (name: String, url: String) + struct URLModel { var id: UUID var name: String @@ -22,25 +24,19 @@ struct URLModel { struct URLModels { var info: [URLModel] - // Network logic - let URLstring: [(String, String)] = [ + // Network logic api call 날려서 받아올 것. + let URLstring: [nameUrl] = [ ("home", "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"), - ("E-Library", "https://42seoul.dkyobobook.co.kr/main.ink"), + ("42STAT", "https://stat.42seoul.kr/home"), ("24Hane", "https://24hoursarenotenough.42seoul.kr"), - ("80000Coding", "https://80000coding.oopy.io"), + ("80kCoding", "https://80000coding.oopy.io"), ("where42", "https://www.where42.kr"), ("cabi", "https://cabi.42seoul.io/"), ("42gg", "https://42gg.kr/"), - ("textart", "https://textart.sh/") + ("textart", "https://textart.sh/"), ] - - mutating func urlSetup() { - URLstring.forEach { (name, url) in - info.append(URLModel(name: name, url: url)) - } - } } From aef20ae9c8b2be9f565e6fbb14f474ba73dad542 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:42:00 +0900 Subject: [PATCH 29/55] feat(window): window UI prototype --- Box42/Menubar/MenubarViewController.swift | 63 +++++++++++------------ Box42/Shared/StateManager.swift | 12 ++++- Box42/UI/GradientView.swift | 37 +++++++++++++ Box42/UI/HoverButton.swift | 46 +++++++++++++++++ Box42/WebView/WebViewList.swift | 20 +++++++ Box42/Window/BoxWindowController.swift | 26 ++++++++-- 6 files changed, 167 insertions(+), 37 deletions(-) create mode 100644 Box42/UI/GradientView.swift create mode 100644 Box42/UI/HoverButton.swift create mode 100644 Box42/WebView/WebViewList.swift diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 0165ed7..09540d6 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -15,8 +15,7 @@ class MenubarViewController: NSWorkspace { let menuBarView = MenuBarView() lazy var eventMonitor: EventMonitor = self.setupEventMonitor() var boxWindowController: BoxWindowController? - - + func menubarViewControllerInit() { self.buttonInit() } @@ -44,11 +43,11 @@ class MenubarViewController: NSWorkspace { statusBarVM.stopRunning() } - func buttonInit() { + func buttonInit() { buttonImageChange("Cat") statusBarVM.statusButtonAppear() - } - + } + func buttonImageChange(_ img: String) { statusBarVM.changeStatusBarIcon(img) } @@ -62,7 +61,7 @@ class MenubarViewController: NSWorkspace { let boxViewController = BoxViewController(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 { @@ -94,7 +93,7 @@ class MenubarViewController: NSWorkspace { popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) } } - + func closePopover(sender: Any?) { popover.performClose(sender) } @@ -102,33 +101,33 @@ class MenubarViewController: NSWorkspace { extension MenubarViewController: MenubarViewControllerDelegate { func toggleWindow(sender: Any?) { - StateManager.shared.setToggleIsShowWindow(); - if StateManager.shared.getToggleIsShowWindow() == false { - boxWindowController?.close() - print("close") - return - } - boxWindowController = BoxWindowController(window: nil) - - // status bar 버튼의 위치를 얻어옵니다. - if let button = statusBarVM.statusBar.statusItem.button, - let window = boxWindowController?.window { - - let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect - - // 버튼 위치 아래에 윈도우를 표시하려면 - let desiredPosition = NSPoint(x: buttonFrame.origin.x, y: buttonFrame.origin.y - window.frame.height) - - // 혹은, 버튼 위치의 중앙에 윈도우를 표시하려면 -// let desiredPosition = NSPoint(x: buttonFrame.midX - window.frame.width / 2, y: buttonFrame.origin.y - window.frame.height) - - // 윈도우의 위치를 설정 - window.setFrameOrigin(desiredPosition) - window.level = .floating + StateManager.shared.setToggleIsShowWindow() + if StateManager.shared.getIsShowWindow() == false { + if let window = boxWindowController?.window { + if window.isVisible { + window.orderOut(sender) + print("hide") + } + } + } else { + if boxWindowController == nil { + boxWindowController = BoxWindowController(window: nil) + } + if let button = statusBarVM.statusBar.statusItem.button, + let window = boxWindowController?.window { + if StateManager.shared.getIsShowFirstWindow() == false { + let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect + let desiredPosition = NSPoint(x: buttonFrame.origin.x, y: buttonFrame.origin.y - window.frame.height) + + window.setFrameOrigin(desiredPosition) + StateManager.shared.setToggleIsShowFirstWindow() + } + window.level = .floating + } + boxWindowController?.showWindow(sender) } - - boxWindowController?.showWindow(sender) } + } protocol MenubarViewControllerDelegate: AnyObject { diff --git a/Box42/Shared/StateManager.swift b/Box42/Shared/StateManager.swift index c5a0fec..0e8ca1d 100644 --- a/Box42/Shared/StateManager.swift +++ b/Box42/Shared/StateManager.swift @@ -11,11 +11,13 @@ class StateManager { private var isPin: Bool! private var isShowCPUUsage: Bool! private var isShowWindow: Bool! + private var isShowFirstWindow: Bool! private init() { isPin = false isShowCPUUsage = false isShowWindow = false + isShowFirstWindow = false } func getIsPin() -> Bool { @@ -34,11 +36,19 @@ class StateManager { isShowCPUUsage.toggle() } - func getToggleIsShowWindow() -> Bool { + func getIsShowWindow() -> Bool { return isShowWindow } func setToggleIsShowWindow() { isShowWindow.toggle() } + + func getIsShowFirstWindow() -> Bool { + return isShowFirstWindow + } + + func setToggleIsShowFirstWindow() { + isShowFirstWindow.toggle() + } } diff --git a/Box42/UI/GradientView.swift b/Box42/UI/GradientView.swift new file mode 100644 index 0000000..7afd87e --- /dev/null +++ b/Box42/UI/GradientView.swift @@ -0,0 +1,37 @@ +// +// GradientView.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import Cocoa + +//layer caching 기법. +//레이어 캐싱: 복잡한 그래픽 연산이 필요한 뷰의 경우 wantsLayer를 true로 설정하고 shouldRasterize 속성을 true로 설정하여 렌더링 결과를 캐시할 수 있습니다. 하지만 이를 과도하게 사용하면 메모리 사용량이 증가할 수 있으므로 주의가 필요합니다. +class GradientView: NSView { + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setupLayerCaching() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.setupLayerCaching() + } + + private func setupLayerCaching() { + self.wantsLayer = true + self.layer?.shouldRasterize = true + self.layer?.rasterizationScale = self.window?.backingScaleFactor ?? 1.0 + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + let startingColor = NSColor(red: 1.0, green: 0.804, blue: 0.0, alpha: 0.9) + let endingColor = NSColor(red: 1.0, green: 0.447, blue: 0.0, alpha: 0.7) + let gradient = NSGradient(starting: startingColor, ending: endingColor) + gradient?.draw(in: self.bounds, angle: 90) + } +} diff --git a/Box42/UI/HoverButton.swift b/Box42/UI/HoverButton.swift new file mode 100644 index 0000000..c7bbcfe --- /dev/null +++ b/Box42/UI/HoverButton.swift @@ -0,0 +1,46 @@ +// +// HoverButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import Cocoa + +class HoverButton: NSButton { + + private var trackingArea: NSTrackingArea? + + override func awakeFromNib() { + super.awakeFromNib() + + self.wantsLayer = true + self.layer?.borderColor = NSColor.black.cgColor + self.layer?.borderWidth = 1.0 + self.layer?.cornerRadius = 5.0 + } + + override func updateTrackingAreas() { + super.updateTrackingAreas() + + if let trackingArea = self.trackingArea { + self.removeTrackingArea(trackingArea) + } + + let options: NSTrackingArea.Options = [.mouseEnteredAndExited, .activeAlways] + trackingArea = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil) + self.addTrackingArea(trackingArea!) + } + + override func mouseEntered(with event: NSEvent) { + // 호버 상태일 때의 스타일을 정의합니다. + self.layer?.backgroundColor = NSColor.gray.cgColor + self.layer?.opacity = 1.0 + } + + override func mouseExited(with event: NSEvent) { + // 호버 상태가 아닐 때의 스타일을 정의합니다. +// self.layer?.backgroundColor = NSColor.white.cgColor + self.layer?.opacity = 0.7 + } +} diff --git a/Box42/WebView/WebViewList.swift b/Box42/WebView/WebViewList.swift new file mode 100644 index 0000000..e4535fc --- /dev/null +++ b/Box42/WebView/WebViewList.swift @@ -0,0 +1,20 @@ +// +// WebViewList.swift +// Box42 +// +// Created by Chanhee Kim on 8/17/23. +// + +import WebKit + +typealias WebViewMapping = [String : WKWebView] + +class WebViewList { + static let shared = WebViewList() + + var list: WebViewMapping! + + private init() { + list = [:] + } +} diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index db80f60..41f4a87 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -8,18 +8,26 @@ import Cocoa class BoxWindowController: NSWindowController { + var windowInstance: NSWindow! + var gradientView: NSView! override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect let styleMask: NSWindow.StyleMask = [.titled, .closable, .resizable, .miniaturizable] - let windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) + windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) windowInstance.title = "Box" windowInstance.styleMask.insert(.resizable) + windowInstance.isReleasedWhenClosed = false + windowInstance.isOpaque = false + + super.init(window: windowInstance) + gradientView = GradientView(frame: contentRect) let boxViewController = BoxViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController - - super.init(window: windowInstance) + windowInstance.contentView?.addSubview(gradientView, positioned: .below, relativeTo: nil) + gradientView.translatesAutoresizingMaskIntoConstraints = false + gradientViewAutoLayout() } required init?(coder: NSCoder) { @@ -28,6 +36,16 @@ class BoxWindowController: NSWindowController { override func windowDidLoad() { super.windowDidLoad() - // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + + func gradientViewAutoLayout() { + if let contentView = windowInstance.contentView { + NSLayoutConstraint.activate([ + gradientView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + gradientView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), + gradientView.topAnchor.constraint(equalTo: contentView.topAnchor), + gradientView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) + ]) + } } } From 1ad2d385fe4f0621b22d86213e5231ee322e3f2c Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 02:42:31 +0900 Subject: [PATCH 30/55] =?UTF-8?q?build(xcode):=20=F0=9F=96=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 57 ++++++++++++++++++- .../contents.xcworkspacedata | 7 +++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++ .../xcshareddata/swiftpm/Package.resolved | 16 ++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 10e6af2..235e566 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -19,6 +19,11 @@ DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; + DE0A915D2A8E348D00D1D6F1 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = DE0A915C2A8E348D00D1D6F1 /* SnapKit */; }; + DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91622A8E6A5400D1D6F1 /* Constants.swift */; }; + DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */; }; + DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */; }; + DE0A91702A8E8BDE00D1D6F1 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */; }; DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A132A8B506600A88DD8 /* keyMapping.sh */; }; @@ -63,6 +68,10 @@ DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; + DE0A91622A8E6A5400D1D6F1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewList.swift; sourceTree = ""; }; + DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverButton.swift; sourceTree = ""; }; + DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; 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 = ""; }; @@ -97,6 +106,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DE0A915D2A8E348D00D1D6F1 /* SnapKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -123,8 +133,8 @@ DE018BB12A5099F900FF0AA3 /* Box42 */ = { isa = PBXGroup; children = ( + DE0A916B2A8E7DC700D1D6F1 /* UI */, DE1F1A202A8B50CA00A88DD8 /* Main */, - DE1F1A182A8B50BB00A88DD8 /* Box */, DEF749302A85655E00D987C8 /* Extensions */, DEB862E82A853F6800278FCD /* Window */, DEB862D22A8511D600278FCD /* Scripts */, @@ -133,6 +143,7 @@ DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, + DE1F1A182A8B50BB00A88DD8 /* Box */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; @@ -155,6 +166,7 @@ DE018C0B2A509BC100FF0AA3 /* URL */, DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, + DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */, ); path = WebView; sourceTree = ""; @@ -191,6 +203,15 @@ path = Menubar; sourceTree = ""; }; + DE0A916B2A8E7DC700D1D6F1 /* UI */ = { + isa = PBXGroup; + children = ( + DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */, + DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */, + ); + path = UI; + sourceTree = ""; + }; DE17AF722A834A1600325BF4 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -223,6 +244,7 @@ children = ( DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */, DE77BA552A82637900713683 /* StateManager.swift */, + DE0A91622A8E6A5400D1D6F1 /* Constants.swift */, ); path = Shared; sourceTree = ""; @@ -295,6 +317,9 @@ dependencies = ( ); name = Box42; + packageProductDependencies = ( + DE0A915C2A8E348D00D1D6F1 /* SnapKit */, + ); productName = Box42; productReference = DE018BAF2A5099F900FF0AA3 /* Box42.app */; productType = "com.apple.product-type.application"; @@ -322,6 +347,9 @@ Base, ); mainGroup = DE018BA62A5099F900FF0AA3; + packageReferences = ( + DE0A915B2A8E348D00D1D6F1 /* XCRemoteSwiftPackageReference "SnapKit" */, + ); productRefGroup = DE018BB02A5099F900FF0AA3 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -368,9 +396,12 @@ DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, + DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */, DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, + DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, DE1F1A242A8B50D500A88DD8 /* BoxButtonHandler.swift in Sources */, + DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, @@ -382,6 +413,7 @@ DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, + DE0A91702A8E8BDE00D1D6F1 /* GradientView.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); @@ -441,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -496,7 +528,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -568,6 +600,25 @@ }; /* End XCConfigurationList section */ +/* Begin XCRemoteSwiftPackageReference section */ + DE0A915B2A8E348D00D1D6F1 /* XCRemoteSwiftPackageReference "SnapKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SnapKit/SnapKit.git"; + requirement = { + kind = exactVersion; + version = 5.6.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + DE0A915C2A8E348D00D1D6F1 /* SnapKit */ = { + isa = XCSwiftPackageProductDependency; + package = DE0A915B2A8E348D00D1D6F1 /* XCRemoteSwiftPackageReference "SnapKit" */; + productName = SnapKit; + }; +/* End XCSwiftPackageProductDependency section */ + /* Begin XCVersionGroup section */ DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */ = { isa = XCVersionGroup; diff --git a/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..19d4e8c --- /dev/null +++ b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "SnapKit", + "repositoryURL": "https://github.com/SnapKit/SnapKit.git", + "state": { + "branch": null, + "revision": "f222cbdf325885926566172f6f5f06af95473158", + "version": "5.6.0" + } + } + ] + }, + "version": 1 +} From 01db66a53cc77e9d19a10f2404625c709904b224 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 03:40:07 +0900 Subject: [PATCH 31/55] =?UTF-8?q?feat(window):=20=EC=9C=88=EB=8F=84?= =?UTF-8?q?=EC=9A=B0=EB=A5=BC=20Movable=ED=95=98=EA=B2=8C=20=EB=A7=8C?= =?UTF-8?q?=EB=93=AD=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/UI/BackGroundView.swift | 63 ++++++++++++++++++++++++++ Box42/Window/BoxWindowController.swift | 11 +++-- 2 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 Box42/UI/BackGroundView.swift diff --git a/Box42/UI/BackGroundView.swift b/Box42/UI/BackGroundView.swift new file mode 100644 index 0000000..d2d2a46 --- /dev/null +++ b/Box42/UI/BackGroundView.swift @@ -0,0 +1,63 @@ +// +// GradientView.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import Cocoa + +// MARK: - BackGround Gradient +//layer caching 기법. +//레이어 캐싱: 복잡한 그래픽 연산이 필요한 뷰의 경우 wantsLayer를 true로 설정하고 shouldRasterize 속성을 true로 설정하여 렌더링 결과를 캐시할 수 있습니다. 하지만 이를 과도하게 사용하면 메모리 사용량이 증가할 수 있으므로 주의가 필요합니다. + +class BackGroundView: NSView { + private var initialLocation: NSPoint? // Mouse Drag Event + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setupLayerCaching() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.setupLayerCaching() + } + + private func setupLayerCaching() { + self.wantsLayer = true + self.layer?.shouldRasterize = true + self.layer?.rasterizationScale = self.window?.backingScaleFactor ?? 1.0 + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + let startingColor = NSColor(red: 1.0, green: 0.804, blue: 0.0, alpha: 0.9) + let endingColor = NSColor(red: 1.0, green: 0.447, blue: 0.0, alpha: 0.7) + let gradient = NSGradient(starting: startingColor, ending: endingColor) + gradient?.draw(in: self.bounds, angle: 90) + } +} + +// MARK: - Mouse Drag Event +extension BackGroundView { + override func mouseDown(with event: NSEvent) { + // 창 내에서의 현재 마우스 위치를 저장합니다. +// self.initialLocation = self.window?.convertPoint(fromScreen: event.locationInWindow) + } + + override func mouseDragged(with event: NSEvent) { +// guard let initialLocation = initialLocation, let window = self.window else { +// return +// } +// +// let currentLocation = window.convertPoint(fromScreen: event.locationInWindow) +// let newOrigin = CGPoint(x: window.frame.origin.x + (currentLocation.x - initialLocation.x), +// y: window.frame.origin.y + (currentLocation.y - initialLocation.y)) +// +// // 창의 위치를 업데이트합니다. +// window.setFrameOrigin(newOrigin) + } +} + diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index 964e402..caa3aca 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -13,15 +13,20 @@ class BoxWindowController: NSWindowController { override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect - let styleMask: NSWindow.StyleMask = [.titled, .closable, .resizable, .miniaturizable] + let styleMask: NSWindow.StyleMask = [.resizable] // [.titled, .closable, .miniaturizable] windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) windowInstance.title = "Box" windowInstance.styleMask.insert(.resizable) windowInstance.isReleasedWhenClosed = false windowInstance.isOpaque = false - + windowInstance.isMovableByWindowBackground = true + super.init(window: windowInstance) - gradientView = GradientView(frame: contentRect) + + windowInstance.isOpaque = false + windowInstance.backgroundColor = .clear + + gradientView = BackGroundView(frame: contentRect) let boxViewController = BoxViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController From 0ea8596df8e5e9a9ac5489610689578a029932cc Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 03:41:07 +0900 Subject: [PATCH 32/55] =?UTF-8?q?feat(contentsView):=20=EC=98=A4=ED=86=A0?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=EC=9D=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=98=EC=97=AC=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EB=94=94=EC=8A=A4=ED=94=8C=EB=A0=88=EC=9D=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=A4=80=EB=B9=84=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 9 +++---- .../Box/BoxBaseContainerViewController.swift | 27 +++++++++---------- Box42/Box/BoxContentsViewGroup.swift | 17 +++++++++--- Box42/Menubar/MenubarViewController.swift | 2 +- Box42/Shared/Constants.swift | 4 +++ 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 8235f4f..0d91469 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - D676A64A2A8C5CEA00B5C319 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = D676A6492A8C5CEA00B5C319 /* SnapKit */; }; DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */; }; DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */; }; DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */; }; @@ -24,7 +23,7 @@ DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91622A8E6A5400D1D6F1 /* Constants.swift */; }; DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */; }; DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */; }; - DE0A91702A8E8BDE00D1D6F1 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */; }; + DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */; }; DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A132A8B506600A88DD8 /* keyMapping.sh */; }; @@ -72,7 +71,7 @@ DE0A91622A8E6A5400D1D6F1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewList.swift; sourceTree = ""; }; DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverButton.swift; sourceTree = ""; }; - DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; + DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackGroundView.swift; sourceTree = ""; }; 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 = ""; }; @@ -208,7 +207,7 @@ isa = PBXGroup; children = ( DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */, - DE0A916F2A8E8BDE00D1D6F1 /* GradientView.swift */, + DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */, ); path = UI; sourceTree = ""; @@ -414,7 +413,7 @@ DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, - DE0A91702A8E8BDE00D1D6F1 /* GradientView.swift in Sources */, + DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index dd38da3..b7400b6 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -6,6 +6,7 @@ // import Cocoa +import SnapKit class BoxBaseContainerViewController: NSViewController { var buttonGroup : BoxButtonViewGroup! @@ -62,22 +63,20 @@ class BoxBaseContainerViewController: NSViewController { view.addSubview(contentGroup) // buttonGroup 오토레이아웃 설정 - buttonGroup.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - buttonGroup.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - buttonGroup.topAnchor.constraint(equalTo: self.view.topAnchor), - buttonGroup.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - buttonGroup.widthAnchor.constraint(equalToConstant: BoxSizeManager.shared.buttonGroupSize.width) - ]) + buttonGroup.snp.makeConstraints { make in + make.leading.equalTo(self.view).offset(Constants.UI.GroupAutolayout) + make.top.equalTo(self.view).offset(Constants.UI.GroupAutolayout) + make.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) + make.width.equalTo(BoxSizeManager.shared.buttonGroupSize.width) + } // contentGroup 오토레이아웃 설정 - contentGroup.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - contentGroup.leadingAnchor.constraint(equalTo: buttonGroup.trailingAnchor), - contentGroup.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - contentGroup.topAnchor.constraint(equalTo: self.view.topAnchor), - contentGroup.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) + contentGroup.snp.makeConstraints { make in + make.leading.equalTo(buttonGroup.snp.trailing) + make.trailing.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) + make.top.equalTo(self.view).offset(Constants.UI.GroupAutolayout) + make.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) + } } func boxViewSizeInit() { diff --git a/Box42/Box/BoxContentsViewGroup.swift b/Box42/Box/BoxContentsViewGroup.swift index 78c9b96..c777a2d 100644 --- a/Box42/Box/BoxContentsViewGroup.swift +++ b/Box42/Box/BoxContentsViewGroup.swift @@ -7,6 +7,7 @@ import Cocoa import WebKit +import SnapKit class BoxContentsViewGroup: NSView { var webVC: WebViewController? @@ -19,9 +20,14 @@ class BoxContentsViewGroup: NSView { super.init(frame: NSRect(x: 0, y: 0, width: BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width, height: BoxSizeManager.shared.buttonGroupSize.height)) self.wantsLayer = true - webVC.view.frame = self.bounds self.addSubview(webVC.view) + + webVC.view.translatesAutoresizingMaskIntoConstraints = false + webVC.view.snp.makeConstraints { make in + make.edges.equalTo(self) + } } + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") @@ -48,10 +54,15 @@ class BoxContentsViewGroup: NSView { print("No WebView found for title: \(sender.title)") return } - - currentWebview.frame = self.bounds // WebView의 크기 및 위치 설정 + + currentWebview.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(currentWebview) + currentWebview.snp.makeConstraints { make in + make.edges.equalTo(self) + } + // WebView 설정 currentWebview.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true currentWebview.configuration.preferences.javaScriptEnabled = true diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index de28917..a409ed8 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -116,7 +116,7 @@ extension MenubarViewController: MenubarViewControllerDelegate { let window = boxWindowController?.window { if StateManager.shared.getIsShowFirstWindow() == false { let buttonFrame = button.window?.convertToScreen(button.frame) ?? NSZeroRect - let desiredPosition = NSPoint(x: buttonFrame.origin.x, y: buttonFrame.origin.y - window.frame.height) + 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() diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift index 3e4ff73..7d46cc6 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -10,4 +10,8 @@ struct Constants { static let InitialName = "home" static let InitialPage = "https://42box.github.io/front-end/" } + + struct UI { + static let GroupAutolayout = 10 + } } From 830424c0f664a75cb38b14ba43ff44b0bdcfc344 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:13:52 +0900 Subject: [PATCH 33/55] =?UTF-8?q?build(tuist):=20Snapkit=20=EB=8F=84?= =?UTF-8?q?=EC=9E=85=EC=9D=84=20=EC=9C=84=ED=95=B4=20=EC=99=B8=EB=B6=80=20?= =?UTF-8?q?=EC=A2=85=EC=86=8D=EC=84=B1=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(tuist): Snapkit을 SwiftPackageManagerDependencies 로 추가합니다. * docs: .gitignore ❤️‍🔥 * build: sh 파일들을 리소스로 옮깁니다. --- .../{Scripts => Resources}/sh/brewInGoinfre.sh | 0 Box42/{Scripts => Resources}/sh/cleanCache.sh | 0 .../sh/exportMacOSInfo.sh | 0 .../sh/importMacOSInfo.sh | 0 Box42/{Scripts => Resources}/sh/keyMapping.sh | 0 Box42/{Scripts => Resources}/sh/nodeInstall.sh | 0 Project.swift | 18 ++++++++++++++---- Tuist/Dependencies.swift | 17 +++++++++++++++++ 8 files changed, 31 insertions(+), 4 deletions(-) rename Box42/{Scripts => Resources}/sh/brewInGoinfre.sh (100%) rename Box42/{Scripts => Resources}/sh/cleanCache.sh (100%) rename Box42/{Scripts => Resources}/sh/exportMacOSInfo.sh (100%) rename Box42/{Scripts => Resources}/sh/importMacOSInfo.sh (100%) rename Box42/{Scripts => Resources}/sh/keyMapping.sh (100%) rename Box42/{Scripts => Resources}/sh/nodeInstall.sh (100%) create mode 100644 Tuist/Dependencies.swift diff --git a/Box42/Scripts/sh/brewInGoinfre.sh b/Box42/Resources/sh/brewInGoinfre.sh similarity index 100% rename from Box42/Scripts/sh/brewInGoinfre.sh rename to Box42/Resources/sh/brewInGoinfre.sh diff --git a/Box42/Scripts/sh/cleanCache.sh b/Box42/Resources/sh/cleanCache.sh similarity index 100% rename from Box42/Scripts/sh/cleanCache.sh rename to Box42/Resources/sh/cleanCache.sh diff --git a/Box42/Scripts/sh/exportMacOSInfo.sh b/Box42/Resources/sh/exportMacOSInfo.sh similarity index 100% rename from Box42/Scripts/sh/exportMacOSInfo.sh rename to Box42/Resources/sh/exportMacOSInfo.sh diff --git a/Box42/Scripts/sh/importMacOSInfo.sh b/Box42/Resources/sh/importMacOSInfo.sh similarity index 100% rename from Box42/Scripts/sh/importMacOSInfo.sh rename to Box42/Resources/sh/importMacOSInfo.sh diff --git a/Box42/Scripts/sh/keyMapping.sh b/Box42/Resources/sh/keyMapping.sh similarity index 100% rename from Box42/Scripts/sh/keyMapping.sh rename to Box42/Resources/sh/keyMapping.sh diff --git a/Box42/Scripts/sh/nodeInstall.sh b/Box42/Resources/sh/nodeInstall.sh similarity index 100% rename from Box42/Scripts/sh/nodeInstall.sh rename to Box42/Resources/sh/nodeInstall.sh diff --git a/Project.swift b/Project.swift index 7ab74f9..0c1c3d1 100644 --- a/Project.swift +++ b/Project.swift @@ -1,3 +1,10 @@ +// +// Project.swift +// Config +// +// Created by Chan on 2023/08/16. +// + import ProjectDescription // MARK: Constants @@ -5,7 +12,9 @@ let projectName = "Box42" let organizationName = "Box42" let bundleID = "com.box42" let targetVersion = "10.15" - +let dependencies: [TargetDependency] = [ + .external(name: "SnapKit"), +] // MARK: Struct let project = Project( name: projectName, @@ -15,15 +24,16 @@ let project = Project( targets: [ Target(name: projectName, platform: .macOS, - product: .app, // unitTests, .appExtension, .framework, dynamicLibrary, staticFramework + product: .app, bundleId: bundleID, deploymentTarget: .macOS(targetVersion: targetVersion), infoPlist: .file(path: "\(projectName)/Resources/Info.plist"), sources: ["\(projectName)/**"], resources: ["\(projectName)/Resources/Assets.xcassets", - "\(projectName)/Resources/Main.storyboard",], + "\(projectName)/Resources/Main.storyboard", + "\(projectName)/Resources/sh/*.sh",], entitlements: "\(projectName)/Resources/Box42.entitlements", - dependencies: [] // tuist generate할 경우 pod install이 자동으로 실행 + dependencies: dependencies ) ], schemes: [], diff --git a/Tuist/Dependencies.swift b/Tuist/Dependencies.swift new file mode 100644 index 0000000..a131a1f --- /dev/null +++ b/Tuist/Dependencies.swift @@ -0,0 +1,17 @@ +// +// Dependencies.swift +// Config +// +// Created by Chan on 2023/08/16. +// + +import ProjectDescription + +let spm = SwiftPackageManagerDependencies([ + .remote(url: "https://github.com/SnapKit/SnapKit", requirement: .exact("5.6.0")), +]) + +let dependencies = Dependencies( + swiftPackageManager: spm, + platforms: [.macOS] +) From 6f615b98074e2cc35820ca8157daf72c3812ed75 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 14:38:15 +0900 Subject: [PATCH 34/55] =?UTF-8?q?refactor(webview):=20=EC=9B=B9=EB=B7=B0?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/WebView.swift | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Box42/WebView/WebView.swift diff --git a/Box42/WebView/WebView.swift b/Box42/WebView/WebView.swift new file mode 100644 index 0000000..0e909ad --- /dev/null +++ b/Box42/WebView/WebView.swift @@ -0,0 +1,42 @@ +// +// WebView.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import WebKit + +class WebView: WKWebView, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + print("userContentController") + } + + + init() { + let preferences = WKPreferences() + preferences.javaScriptEnabled = true + preferences.javaScriptCanOpenWindowsAutomatically = true + + let contentController = WKUserContentController() + let configuration = WKWebViewConfiguration() + configuration.preferences = preferences + configuration.userContentController = contentController + + super.init(frame: .zero, configuration: configuration) + + contentController.add(self, name: "box") // Moved after super.init + + 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() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} From 0508e030ad08521ac3949e7e1ee640d67f9398f9 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 14:38:36 +0900 Subject: [PATCH 35/55] =?UTF-8?q?refactor(webview):=20=EC=9B=B9=EB=B7=B0?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/UI/BackGroundView.swift | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/Box42/UI/BackGroundView.swift b/Box42/UI/BackGroundView.swift index d2d2a46..de430ed 100644 --- a/Box42/UI/BackGroundView.swift +++ b/Box42/UI/BackGroundView.swift @@ -12,8 +12,6 @@ import Cocoa //레이어 캐싱: 복잡한 그래픽 연산이 필요한 뷰의 경우 wantsLayer를 true로 설정하고 shouldRasterize 속성을 true로 설정하여 렌더링 결과를 캐시할 수 있습니다. 하지만 이를 과도하게 사용하면 메모리 사용량이 증가할 수 있으므로 주의가 필요합니다. class BackGroundView: NSView { - private var initialLocation: NSPoint? // Mouse Drag Event - override init(frame frameRect: NSRect) { super.init(frame: frameRect) self.setupLayerCaching() @@ -40,24 +38,3 @@ class BackGroundView: NSView { } } -// MARK: - Mouse Drag Event -extension BackGroundView { - override func mouseDown(with event: NSEvent) { - // 창 내에서의 현재 마우스 위치를 저장합니다. -// self.initialLocation = self.window?.convertPoint(fromScreen: event.locationInWindow) - } - - override func mouseDragged(with event: NSEvent) { -// guard let initialLocation = initialLocation, let window = self.window else { -// return -// } -// -// let currentLocation = window.convertPoint(fromScreen: event.locationInWindow) -// let newOrigin = CGPoint(x: window.frame.origin.x + (currentLocation.x - initialLocation.x), -// y: window.frame.origin.y + (currentLocation.y - initialLocation.y)) -// -// // 창의 위치를 업데이트합니다. -// window.setFrameOrigin(newOrigin) - } -} - From 3b44fbdf0af00bf06cfd9f823a29a237ab03c89e Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 14:39:20 +0900 Subject: [PATCH 36/55] =?UTF-8?q?refactor(webview):=20=EC=9B=B9=EB=B7=B0?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/BoxContentsViewGroup.swift | 1 - Box42/WebView/WebViewController.swift | 60 +++++++++------------------ 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/Box42/Box/BoxContentsViewGroup.swift b/Box42/Box/BoxContentsViewGroup.swift index c777a2d..40320d9 100644 --- a/Box42/Box/BoxContentsViewGroup.swift +++ b/Box42/Box/BoxContentsViewGroup.swift @@ -11,7 +11,6 @@ import SnapKit class BoxContentsViewGroup: NSView { var webVC: WebViewController? - var webView: WKWebView! var preferencesVC = PreferencesViewController() init() { diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 55991ed..ac3eddb 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -9,7 +9,7 @@ import Cocoa import WebKit import Combine -class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate { +class WebViewController: NSViewController { var URLVM = WebViewModel() var webView: WKWebView! @@ -17,24 +17,32 @@ class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, var cancellables: Set = [] override func loadView() { - self.webView = addWebView() + self.webView = WebView() self.view = webView - loadWebViewInit() webViewInit() + loadWebviewInit() // bindViewModel() } - func loadWebViewInit() { + func loadWebviewInit() { URLVM.setUpURLdict() - for (key, value) in URLVM.URLdict { - let wkWebView = addWebView() - WebViewList.shared.list[key] = wkWebView - DispatchQueue.main.async { - wkWebView.load(self.URLVM.requestURL(value)) - } - } + loadAllWebview() + } + + func loadWebView(_ name: String, _ url: URL) { + let wkWebView = WebView() + WebViewList.shared.list[name] = wkWebView + DispatchQueue.main.async { + wkWebView.load(self.URLVM.requestURL(url)) + } } + func loadAllWebview() { + for (name, URL) in URLVM.URLdict { + loadWebView(name, URL) + } + } + func webViewInit() { DispatchQueue.main.async { self.webView.load(self.URLVM.requestURL(self.URLVM.safeURL())) @@ -42,41 +50,13 @@ class WebViewController: NSViewController, WKScriptMessageHandler, WKUIDelegate, } func bindViewModel() { - // Whenever URLdict changes, it will call loadWebViewInit URLVM.$URLdict .sink { [weak self] _ in - self?.loadWebViewInit() + self?.loadAllWebview() } .store(in: &cancellables) } - func addWebView() -> WKWebView { - let preferences = WKPreferences() - preferences.javaScriptEnabled = true - preferences.javaScriptCanOpenWindowsAutomatically = true - - let contentController = WKUserContentController() - contentController.add(self, name: "box") - - let configuration = WKWebViewConfiguration() - configuration.preferences = preferences - configuration.userContentController = contentController - - let webView = WKWebView(frame: .zero, configuration: configuration) - - webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true - webView.configuration.preferences.javaScriptEnabled = true - - webView.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") - if #available(macOS 11.0, *) { - webView.configuration.defaultWebpagePreferences.allowsContentJavaScript = true - } - - webView.uiDelegate = self - webView.navigationDelegate = self - return webView - } - override func viewDidLoad() { super.viewDidLoad() } From c1fa4edada74273090dcba7d53652f087d6f6405 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 14:39:51 +0900 Subject: [PATCH 37/55] =?UTF-8?q?fix(storage):=20auto=20cache=20clean=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Scripts/AppleScripts+ShowMessage.swift | 42 ++++++++++++++++++++ Box42/Shared/StateManager.swift | 14 +++++++ Box42/System/Storage.swift | 34 +++++++++++++++- Box42/System/StorageConfig.swift | 2 +- 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 Box42/Scripts/AppleScripts+ShowMessage.swift diff --git a/Box42/Scripts/AppleScripts+ShowMessage.swift b/Box42/Scripts/AppleScripts+ShowMessage.swift new file mode 100644 index 0000000..3a7411b --- /dev/null +++ b/Box42/Scripts/AppleScripts+ShowMessage.swift @@ -0,0 +1,42 @@ +// +// AppleScripts+ShowMessage.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import Foundation +import AppKit + +func showMessageWithAppleScript(_ message: String) { + let appleScript = """ + display dialog "\(message)" buttons {"OK"} default button "OK" + """ + + var error: NSDictionary? + if let scriptObject = NSAppleScript(source: appleScript) { + scriptObject.executeAndReturnError(&error) + if let error = error { + print("AppleScript Error: \(error)") + } + } +} + +func showMessageWithAppleScript(_ message: String, _ button: String, completion: @escaping (String?) -> Void) { + let appleScript = """ + display dialog "\(message)" buttons {"\(button)", "취소"} default button "\(button)" + """ + + var error: NSDictionary? + if let scriptObject = NSAppleScript(source: appleScript) { + let output = scriptObject.executeAndReturnError(&error) + let buttonReturned = output.forKeyword(keyDirectObject) + print("output", output.description) +// completion(output.stringValue) + completion(buttonReturned?.stringValue) + if let error = error { + print("AppleScript Error: \(error)") + completion(nil) + } + } +} diff --git a/Box42/Shared/StateManager.swift b/Box42/Shared/StateManager.swift index 0e8ca1d..e73da57 100644 --- a/Box42/Shared/StateManager.swift +++ b/Box42/Shared/StateManager.swift @@ -12,12 +12,14 @@ class StateManager { 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 } func getIsPin() -> Bool { @@ -51,4 +53,16 @@ class StateManager { func setToggleIsShowFirstWindow() { isShowFirstWindow.toggle() } + + func getIsAutoStorage() -> Bool { + return isAutoStorage + } + + func setOffIsAutoStorage() { + isAutoStorage = false + } + + func setOnIsAutoStorage() { + isAutoStorage = true + } } diff --git a/Box42/System/Storage.swift b/Box42/System/Storage.swift index 8c55f25..6b06a22 100644 --- a/Box42/System/Storage.swift +++ b/Box42/System/Storage.swift @@ -54,6 +54,11 @@ class Storage { func storageTimerEvent(){ storageTimer?.invalidate() + + if StateManager.shared.getIsAutoStorage() == false { + return + } + storageTimer = Timer.scheduledTimer(withTimeInterval: config.period.rawValue, repeats: true, block: { [weak self] _ in guard let self = self else { return } @@ -63,11 +68,34 @@ class Storage { } if let usedUsage = self.usedUsage, let totalUsage = self.totalUsage, totalUsage != 0 { - let usagePercentage = usedUsage / totalUsage + let usagePercentage = (totalUsage - usedUsage) / totalUsage if usagePercentage < self.config.threshold.rawValue { self.cleanSh() self.count += 1 - print(self.count > 5 ? "캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요." : "\(usedUsage.roundedToTwoDecimalPlaces) GB", "Storage used is less than 30%") + if self.count > 2 { + showMessageWithAppleScript("캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요.", "재시작") { button in + print("timer") + dump(button) + if let button = button { + switch button { + case "재시작": + StateManager.shared.setOnIsAutoStorage() + print("재시작 버튼을 클릭했습니다.") + case "취소": + // 취소 관련 로직 실행 + print("취소 버튼을 클릭했습니다.") + default: + break + } + } + } + + StateManager.shared.setOffIsAutoStorage() + // 여기서도 타이머를 중지시켜야 합니다. + self.storageTimer?.invalidate() + } else { + print("\(usedUsage.roundedToTwoDecimalPlaces) GB", "Storage used is less than 30%") + } } else { self.count = 0 } @@ -75,8 +103,10 @@ class Storage { print("Failed to get storage usage details") } }) + storageTimer?.fire() } + func cleanSh() { if let scriptPath = Bundle.main.path(forResource: "cleanCache", ofType: "sh") { diff --git a/Box42/System/StorageConfig.swift b/Box42/System/StorageConfig.swift index 1eec523..7b9f615 100644 --- a/Box42/System/StorageConfig.swift +++ b/Box42/System/StorageConfig.swift @@ -27,7 +27,7 @@ class StorageConfig: ObservableObject { @Published var threshold: StorageThreshold @Published var period: StoragePeriod - init(_ threshold: StorageThreshold = .percentage05, _ period: StoragePeriod = .period3s) { + init(_ threshold: StorageThreshold = .percentage10, _ period: StoragePeriod = .period3s) { self.threshold = threshold self.period = period } From 4714278032f140d7861f1f31c26b474aa3de7ae6 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Fri, 18 Aug 2023 14:40:14 +0900 Subject: [PATCH 38/55] =?UTF-8?q?chore:=20=EC=93=B8=EB=AA=A8=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=9E=A0=EC=8B=9C=20=EC=9E=A0?= =?UTF-8?q?=EA=B8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 8 ++++++++ Box42/Box/BoxBaseContainerViewController.swift | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 0d91469..795d9b6 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -24,6 +24,8 @@ DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */; }; DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */; }; DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */; }; + DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91772A8F014F00D1D6F1 /* WebView.swift */; }; + DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */; }; DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A132A8B506600A88DD8 /* keyMapping.sh */; }; @@ -72,6 +74,8 @@ DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewList.swift; sourceTree = ""; }; DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverButton.swift; sourceTree = ""; }; DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackGroundView.swift; sourceTree = ""; }; + DE0A91772A8F014F00D1D6F1 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; + DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppleScripts+ShowMessage.swift"; sourceTree = ""; }; 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 = ""; }; @@ -167,6 +171,7 @@ DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */, + DE0A91772A8F014F00D1D6F1 /* WebView.swift */, ); path = WebView; sourceTree = ""; @@ -266,6 +271,7 @@ children = ( DEB862DE2A85348600278FCD /* sh */, DEB862DB2A85347400278FCD /* Scripts.swift */, + DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */, ); path = Scripts; sourceTree = ""; @@ -381,6 +387,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, @@ -414,6 +421,7 @@ DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */, + DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index b7400b6..82f7ca1 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -16,7 +16,7 @@ class BoxBaseContainerViewController: NSViewController { self.view = NSView() // 뷰 컨트롤러의 뷰 설정 buttonGroup = BoxButtonViewGroupInit() contentGroup = BoxContentsViewGroup() - panGestureInit() +// panGestureInit() viewInit() } From 5876cb93a712792f629fab3c89035066a94223cc Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sat, 19 Aug 2023 04:18:18 +0900 Subject: [PATCH 39/55] =?UTF-8?q?feat(Button=20UI):=20=EA=B8=B0=EC=A1=B4?= =?UTF-8?q?=20ContainerView=EB=A5=BC=20Split=20View=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 111 ++++++++---------- Box42/BoxBaseSplitView.swift | 22 ++++ Box42/Shared/Constants.swift | 2 +- Box42/UI/MovableContainerView.swift | 24 ++++ 4 files changed, 97 insertions(+), 62 deletions(-) create mode 100644 Box42/BoxBaseSplitView.swift create mode 100644 Box42/UI/MovableContainerView.swift diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 82f7ca1..6aaa7de 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -9,25 +9,30 @@ import Cocoa import SnapKit class BoxBaseContainerViewController: NSViewController { - var buttonGroup : BoxButtonViewGroup! - var contentGroup : BoxContentsViewGroup! + var splitView: BoxBaseSplitView! = BoxBaseSplitView() + var contentGroup: BoxContentsViewGroup! = BoxContentsViewGroup() + var toolbarGroup: BoxToolbarViewGroup! = BoxToolbarViewGroup() + var buttonGroup: BoxButtonViewGroup! + var leftContainer: MovableContainerView! override func loadView() { - self.view = NSView() // 뷰 컨트롤러의 뷰 설정 + self.view = NSView() + self.view.addSubview(splitView) + splitView.delegate = self + buttonGroup = BoxButtonViewGroupInit() - contentGroup = BoxContentsViewGroup() -// panGestureInit() + + leftContainerInit() viewInit() } - + func BoxButtonViewGroupInit() -> BoxButtonViewGroup { let buttonGroup = BoxButtonViewGroup { sender in self.clickBtn(sender: sender) } - view.addSubview(buttonGroup) return buttonGroup } - + func clickBtn(sender: NSButton) { guard let clickCount = NSApp.currentEvent?.clickCount else { return } if sender.title == "Preferences" { @@ -39,80 +44,64 @@ class BoxBaseContainerViewController: NSViewController { WebViewList.shared.list[sender.title]!.reload() print("Dobule Click") } else if clickCount > 2 { -// let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) -// WebViewList.shared.list[sender.title]!.load(rqURL) + // let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) + // WebViewList.shared.list[sender.title]!.load(rqURL) print("Triple Click") } else if clickCount < 2 { contentGroup.removeAllSubviews() contentGroup.showWebviews(sender) } } - - private func panGestureInit() { - let panRecognizer = NSPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) - self.view.addGestureRecognizer(panRecognizer) // 뷰 컨트롤러의 뷰에 제스처 추가 + + private func leftContainerInit() { + leftContainer = MovableContainerView() + leftContainer.addSubview(buttonGroup) + leftContainer.addSubview(toolbarGroup) } func viewInit() { self.boxViewSizeInit() - self.buttonBoxGroupInit() - self.contentsGroupInit() - // buttonGroup과 contentGroup을 self에 추가합니다. - view.addSubview(buttonGroup) - view.addSubview(contentGroup) - - // buttonGroup 오토레이아웃 설정 - buttonGroup.snp.makeConstraints { make in - make.leading.equalTo(self.view).offset(Constants.UI.GroupAutolayout) + 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.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) - make.width.equalTo(BoxSizeManager.shared.buttonGroupSize.width) + make.left.equalTo(self.view).offset(Constants.UI.GroupAutolayout) + make.right.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) } - - // contentGroup 오토레이아웃 설정 - contentGroup.snp.makeConstraints { make in - make.leading.equalTo(buttonGroup.snp.trailing) - make.trailing.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) - make.top.equalTo(self.view).offset(Constants.UI.GroupAutolayout) - make.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) + + toolbarGroup.snp.makeConstraints { make in + make.top.equalTo(leftContainer).offset(Constants.UI.GroupAutolayout) + make.left.right.equalTo(leftContainer) + } + + buttonGroup.snp.makeConstraints { make in + make.top.equalTo(toolbarGroup.snp.bottom).offset(Constants.UI.GroupAutolayout) + make.left.right.bottom.equalTo(leftContainer) } } - + func boxViewSizeInit() { self.view.frame.size.width = BoxSizeManager.shared.size.width self.view.frame.size.height = BoxSizeManager.shared.size.height } - - func contentsGroupInit() { - self.contentGroup.frame.size.width = BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width - self.contentGroup.frame.size.height = BoxSizeManager.shared.size.height - } - - func buttonBoxGroupInit() { - self.buttonGroup.frame.size.width = BoxSizeManager.shared.buttonGroupSize.width - self.buttonGroup.frame.size.height = BoxSizeManager.shared.buttonGroupSize.height - } } -extension BoxBaseContainerViewController { - // 추후 논의. 내부 panGesture로 View크기 증감 - @objc private func handlePanGesture(_ recognizer: NSPanGestureRecognizer) { - guard let view = recognizer.view else { return } - - // 사용자가 드래그한 변화량을 가져옵니다. - let translation = recognizer.translation(in: view) - - // 드래그로 인한 크기 변화를 계산합니다. - let newWidth = view.frame.width + translation.x - let newHeight = view.frame.height + translation.y - - // 크기를 적용합니다. - view.setFrameSize(NSSize(width: newWidth, height: newHeight)) - - // 변화량을 리셋합니다. - recognizer.setTranslation(.zero, in: view) - - print(newWidth, newHeight) +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 } } diff --git a/Box42/BoxBaseSplitView.swift b/Box42/BoxBaseSplitView.swift new file mode 100644 index 0000000..d432a99 --- /dev/null +++ b/Box42/BoxBaseSplitView.swift @@ -0,0 +1,22 @@ +// +// BoxBaseSplitView.swift +// Box42 +// +// Created by Chanhee Kim on 8/19/23. +// + +import AppKit + +class BoxBaseSplitView: NSSplitView { + init() { + super.init(frame: .zero) + + self.isVertical = true + self.dividerStyle = .thin + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Box42/Shared/Constants.swift b/Box42/Shared/Constants.swift index 7d46cc6..322faa9 100644 --- a/Box42/Shared/Constants.swift +++ b/Box42/Shared/Constants.swift @@ -12,6 +12,6 @@ struct Constants { } struct UI { - static let GroupAutolayout = 10 + static let GroupAutolayout = 12 } } diff --git a/Box42/UI/MovableContainerView.swift b/Box42/UI/MovableContainerView.swift new file mode 100644 index 0000000..69c4042 --- /dev/null +++ b/Box42/UI/MovableContainerView.swift @@ -0,0 +1,24 @@ +// +// MovableContainerView.swift +// Box42 +// +// Created by Chanhee Kim on 8/19/23. +// + +import AppKit + +class MovableContainerView: NSView { + init() { + super.init(frame: NSRect(x: 0, y: 0, width: 300, height: BoxSizeManager.shared.size.height)) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func mouseDown(with event: NSEvent) { + if let window = self.window { + window.performDrag(with: event) + } + } +} From 211a2a8a55649e0ac54afe875bb31eb0a5d8d3a9 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sat, 19 Aug 2023 04:19:19 +0900 Subject: [PATCH 40/55] =?UTF-8?q?feat(BoxUI):=20toolbar=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42.xcodeproj/project.pbxproj | 72 ++++++++-- Box42/Box/BoxContentsViewGroup.swift | 24 ++-- Box42/Box/BoxToolbarViewGroup.swift | 31 +++++ Box42/Extensions/NSImage.swift | 30 +++++ Box42/Main/BoxButtonHandler.swift | 34 ----- Box42/Main/BoxViewController.swift | 27 +++- .../Assets.xcassets/Icons/Contents.json | 6 + .../arrow.clockwise.imageset/Contents.json | 21 +++ .../arrow.clockwise@2x.png | Bin 0 -> 1114 bytes .../Icons/arrow.left.imageset/Contents.json | 21 +++ .../arrow.left.imageset/arrow.left@2x.png | Bin 0 -> 677 bytes .../Icons/arrow.right.imageset/Contents.json | 21 +++ .../arrow.right.imageset/arrow.right@2x.png | Bin 0 -> 633 bytes .../Icons/doc.on.doc.imageset/Contents.json | 21 +++ .../doc.on.doc.imageset/doc.on.doc@2x.png | Bin 0 -> 1301 bytes .../Icons/ellipsis.imageset/Contents.json | 21 +++ .../Icons/ellipsis.imageset/ellipsis@2x.png | Bin 0 -> 459 bytes .../figure.skating.imageset/Contents.json | 21 +++ .../figure.skating@2x.png | Bin 0 -> 1333 bytes .../Contents.json | 21 +++ .../figure.snowboarding@2x.png | Bin 0 -> 1277 bytes .../figure.surfing.imageset/Contents.json | 21 +++ .../figure.surfing@2x.png | Bin 0 -> 1570 bytes .../Icons/minus.imageset/Contents.json | 21 +++ .../Icons/minus.imageset/minus@2x.png | Bin 0 -> 212 bytes .../Icons/pin.fill.imageset/Contents.json | 21 +++ .../Icons/pin.fill.imageset/pin.fill@2x.png | Bin 0 -> 890 bytes .../Icons/pin.imageset/Contents.json | 21 +++ .../Icons/pin.imageset/pin@2x.png | Bin 0 -> 986 bytes .../Icons/plus.imageset/Contents.json | 21 +++ .../Icons/plus.imageset/plus@2x.png | Bin 0 -> 354 bytes .../Icons/shippingbox.imageset/Contents.json | 21 +++ .../shippingbox.imageset/shippingbox@2x.png | Bin 0 -> 1530 bytes .../sidebar.leading.imageset/Contents.json | 21 +++ .../sidebar.leading@2x.png | Bin 0 -> 681 bytes Box42/Shared/BoxSizeManager.swift | 2 + Box42/Toolbar/ToolbarViewController.swift | 57 ++++++++ Box42/Toolbar/View/DisplayURLInToolbar.swift | 33 +++++ Box42/Toolbar/View/GoBackInToolbar.swift | 31 +++++ Box42/Toolbar/View/GoForwardInToolbar.swift | 31 +++++ .../Toolbar/View/GoHomePageViaToolbar().swift | 31 +++++ .../Toolbar/View/RefreshPageViaToolbar.swift | 31 +++++ Box42/Toolbar/View/SideBarLeading.swift | 31 +++++ Box42/UI/BackGroundView.swift | 40 ------ Box42/Window/BoxWindowController.swift | 125 ++++++++++++++---- 45 files changed, 804 insertions(+), 126 deletions(-) create mode 100644 Box42/Box/BoxToolbarViewGroup.swift create mode 100644 Box42/Extensions/NSImage.swift delete mode 100644 Box42/Main/BoxButtonHandler.swift create mode 100644 Box42/Resources/Assets.xcassets/Icons/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/arrow.clockwise@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/arrow.left@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/arrow.right@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/doc.on.doc@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/ellipsis@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/figure.skating@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/figure.snowboarding@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/figure.surfing@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/minus.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/minus.imageset/minus@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/pin.fill@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/pin.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/pin.imageset/pin@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/plus.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/plus.imageset/plus@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/shippingbox@2x.png create mode 100644 Box42/Resources/Assets.xcassets/Icons/sidebar.leading.imageset/Contents.json create mode 100644 Box42/Resources/Assets.xcassets/Icons/sidebar.leading.imageset/sidebar.leading@2x.png create mode 100644 Box42/Toolbar/ToolbarViewController.swift create mode 100644 Box42/Toolbar/View/DisplayURLInToolbar.swift create mode 100644 Box42/Toolbar/View/GoBackInToolbar.swift create mode 100644 Box42/Toolbar/View/GoForwardInToolbar.swift create mode 100644 Box42/Toolbar/View/GoHomePageViaToolbar().swift create mode 100644 Box42/Toolbar/View/RefreshPageViaToolbar.swift create mode 100644 Box42/Toolbar/View/SideBarLeading.swift delete mode 100644 Box42/UI/BackGroundView.swift diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 795d9b6..89f0ba3 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -23,22 +23,32 @@ DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91622A8E6A5400D1D6F1 /* Constants.swift */; }; DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */; }; DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */; }; - DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */; }; DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91772A8F014F00D1D6F1 /* WebView.swift */; }; DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */; }; + DE0A917F2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */; }; + DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */; }; + DE0A91862A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91852A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift */; }; + DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */; }; + DE0A918D2A8F88BC00D1D6F1 /* GoBackInToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */; }; + DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */; }; + DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91972A8F977F00D1D6F1 /* ToolbarViewController.swift */; }; + DE0A91A22A8FAC3F00D1D6F1 /* WebView+CustomScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */; }; + DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */; }; DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; DE1F1A162A8B506600A88DD8 /* keyMapping.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A132A8B506600A88DD8 /* keyMapping.sh */; }; 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 */; }; - DE1F1A242A8B50D500A88DD8 /* BoxButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */; }; DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A222A8B50D500A88DD8 /* BoxViewModel.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 */; }; DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */; }; + DE24E6352A8FE02A00E29F5D /* MovableContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE24E6342A8FE02A00E29F5D /* MovableContainerView.swift */; }; + 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 */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; @@ -73,22 +83,32 @@ DE0A91622A8E6A5400D1D6F1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewList.swift; sourceTree = ""; }; DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverButton.swift; sourceTree = ""; }; - DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackGroundView.swift; sourceTree = ""; }; DE0A91772A8F014F00D1D6F1 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppleScripts+ShowMessage.swift"; sourceTree = ""; }; + DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BoxToolbarViewGroup.swift; path = Box/BoxToolbarViewGroup.swift; sourceTree = ""; }; + DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GoHomePageViaToolbar().swift"; sourceTree = ""; }; + DE0A91852A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshPageViaToolbar.swift; sourceTree = ""; }; + DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoForwardInToolbar.swift; sourceTree = ""; }; + DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoBackInToolbar.swift; sourceTree = ""; }; + DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayURLInToolbar.swift; sourceTree = ""; }; + DE0A91972A8F977F00D1D6F1 /* ToolbarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarViewController.swift; sourceTree = ""; }; + DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebView+CustomScroller.swift"; sourceTree = ""; }; + DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideBarLeading.swift; sourceTree = ""; }; 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 = ""; }; DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxContentsViewGroup.swift; path = Box/BoxContentsViewGroup.swift; sourceTree = ""; }; DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxButtonViewGroup.swift; path = Box/BoxButtonViewGroup.swift; sourceTree = ""; }; - DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxButtonHandler.swift; path = Main/BoxButtonHandler.swift; sourceTree = ""; }; DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewModel.swift; path = Main/BoxViewModel.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 = ""; }; DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageConfig.swift; sourceTree = ""; }; + DE24E6342A8FE02A00E29F5D /* MovableContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovableContainerView.swift; sourceTree = ""; }; + 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 = ""; }; DE77BA502A82580400713683 /* MenubarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarViewModel.swift; sourceTree = ""; }; DE77BA552A82637900713683 /* StateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateManager.swift; sourceTree = ""; }; @@ -147,6 +167,7 @@ DE018C0C2A509BDF00FF0AA3 /* Resources */, DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, + DE0A917D2A8F864300D1D6F1 /* Toolbar */, DE1F1A182A8B50BB00A88DD8 /* Box */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); @@ -212,11 +233,34 @@ isa = PBXGroup; children = ( DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */, - DE0A916F2A8E8BDE00D1D6F1 /* BackGroundView.swift */, + DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */, + DE24E6342A8FE02A00E29F5D /* MovableContainerView.swift */, ); path = UI; sourceTree = ""; }; + DE0A917D2A8F864300D1D6F1 /* Toolbar */ = { + isa = PBXGroup; + children = ( + DE0A919E2A8FA15300D1D6F1 /* View */, + DE0A91972A8F977F00D1D6F1 /* ToolbarViewController.swift */, + ); + path = Toolbar; + sourceTree = ""; + }; + DE0A919E2A8FA15300D1D6F1 /* View */ = { + isa = PBXGroup; + children = ( + DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */, + DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */, + DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */, + DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */, + DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */, + DE0A91852A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift */, + ); + path = View; + sourceTree = ""; + }; DE17AF722A834A1600325BF4 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -227,9 +271,11 @@ DE1F1A182A8B50BB00A88DD8 /* Box */ = { isa = PBXGroup; children = ( + DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */, DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, + DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); name = Box; sourceTree = ""; @@ -237,7 +283,6 @@ DE1F1A202A8B50CA00A88DD8 /* Main */ = { isa = PBXGroup; children = ( - DE1F1A212A8B50D500A88DD8 /* BoxButtonHandler.swift */, DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */, DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */, ); @@ -303,6 +348,7 @@ DE874F5E2A5935CC00FC3B77 /* String.swift */, DEF749312A85657600D987C8 /* NSScreen.swift */, DE1F1A302A8BD68F00A88DD8 /* Double.swift */, + DE24E63A2A8FE93900E29F5D /* NSImage.swift */, ); path = Extensions; sourceTree = ""; @@ -387,10 +433,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */, DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, + DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, @@ -400,29 +448,37 @@ DE77BA512A82580400713683 /* MenubarViewModel.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 */, DE1F1A252A8B50D500A88DD8 /* BoxViewModel.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 */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, - DE1F1A242A8B50D500A88DD8 /* BoxButtonHandler.swift in Sources */, DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.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 */, DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, + DE24E6352A8FE02A00E29F5D /* MovableContainerView.swift in Sources */, DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, + DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, - DE0A91702A8E8BDE00D1D6F1 /* BackGroundView.swift in Sources */, + DE0A91A22A8FAC3F00D1D6F1 /* WebView+CustomScroller.swift in Sources */, DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, + DE0A917F2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Box42/Box/BoxContentsViewGroup.swift b/Box42/Box/BoxContentsViewGroup.swift index 40320d9..0493128 100644 --- a/Box42/Box/BoxContentsViewGroup.swift +++ b/Box42/Box/BoxContentsViewGroup.swift @@ -5,7 +5,6 @@ // Created by Chanhee Kim on 8/13/23. // -import Cocoa import WebKit import SnapKit @@ -14,15 +13,18 @@ class BoxContentsViewGroup: NSView { var preferencesVC = PreferencesViewController() init() { - let webVC = WebViewController(nibName: nil, bundle: nil) + webVC = WebViewController(nibName: nil, bundle: nil) super.init(frame: NSRect(x: 0, y: 0, width: BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width, height: BoxSizeManager.shared.buttonGroupSize.height)) + self.frame.size.width = BoxSizeManager.shared.size.width - BoxSizeManager.shared.buttonGroupSize.width + self.frame.size.height = BoxSizeManager.shared.size.height + self.wantsLayer = true - self.addSubview(webVC.view) + self.addSubview(webVC!.view) - webVC.view.translatesAutoresizingMaskIntoConstraints = false - webVC.view.snp.makeConstraints { make in + webVC?.view.translatesAutoresizingMaskIntoConstraints = false + webVC?.view.snp.makeConstraints { make in make.edges.equalTo(self) } } @@ -54,25 +56,21 @@ class BoxContentsViewGroup: NSView { return } - currentWebview.translatesAutoresizingMaskIntoConstraints = false - + WebViewList.shared.hostingname = sender.title + WebViewList.shared.hostingWebView = currentWebview + self.addSubview(currentWebview) currentWebview.snp.makeConstraints { make in make.edges.equalTo(self) } - // WebView 설정 - currentWebview.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true - currentWebview.configuration.preferences.javaScriptEnabled = true - - // WebView 내용 로드 확인 (옵셔널) if currentWebview.url == nil { print("WebView for \(sender.title) has no content loaded.") } currentWebview.viewDidMoveToSuperview() + currentWebview.becomeFirstResponder() } } - diff --git a/Box42/Box/BoxToolbarViewGroup.swift b/Box42/Box/BoxToolbarViewGroup.swift new file mode 100644 index 0000000..ac17e8c --- /dev/null +++ b/Box42/Box/BoxToolbarViewGroup.swift @@ -0,0 +1,31 @@ +// +// BoxToolbarViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit +import SnapKit + +class BoxToolbarViewGroup: NSView { + var toolbarVC: ToolbarViewController? + + 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)) + + self.wantsLayer = true +// self.addSubview(toolbarVC!.view) + + toolbarVC?.view.translatesAutoresizingMaskIntoConstraints = false + toolbarVC?.view.snp.makeConstraints { make in + make.edges.equalTo(self) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Box42/Extensions/NSImage.swift b/Box42/Extensions/NSImage.swift new file mode 100644 index 0000000..602020e --- /dev/null +++ b/Box42/Extensions/NSImage.swift @@ -0,0 +1,30 @@ +// +// NSImage.swift +// Box42 +// +// Created by Chanhee Kim on 8/19/23. +// + +import Cocoa + +extension NSImage { + func resized(to newSize: CGSize) -> NSImage? { + if let bitmapRepresentation = NSBitmapImageRep( + bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height), + bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, + colorSpaceName: NSColorSpaceName.deviceRGB, bytesPerRow: 0, bitsPerPixel: 0) { + + bitmapRepresentation.size = newSize + NSGraphicsContext.saveGraphicsState() + NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: bitmapRepresentation) + self.draw(in: NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height), from: .zero, operation: .copy, fraction: 1.0) + NSGraphicsContext.restoreGraphicsState() + + let resizedImage = NSImage(size: newSize) + resizedImage.addRepresentation(bitmapRepresentation) + return resizedImage + } + + return nil + } +} diff --git a/Box42/Main/BoxButtonHandler.swift b/Box42/Main/BoxButtonHandler.swift deleted file mode 100644 index 2c5440c..0000000 --- a/Box42/Main/BoxButtonHandler.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// BoxButtonHandler.swift -// Box42 -// -// Created by Chanhee Kim on 8/11/23. -// - -import Cocoa - -class BoxButtonHandler { - func clickBtn(sender: NSButton) {} -// guard let clickCount = NSApp.currentEvent?.clickCount else { return } -// if sender.title == "Preferences" { -//// boxView.contentGroup.subviews.removeAll() -//// boxView.contentGroup.addSubview(preferencesVC.view) -//// preferencesVC.viewDidAppear() -// return -// } -// if clickCount == 2 { -// WebViewList.shared.list[sender.title]!.reload() -// print("Dobule Click") -// } else if clickCount > 2 { -//// let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) -//// WebViewList.shared.list[sender.title]!.load(rqURL) -// print("Triple Click") -// } else if clickCount < 2 { -//// boxView.contentGroup.subviews.removeAll() -//// boxView.contentGroup.addSubview(WebViewList.shared.list[sender.title]!) -// WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true -// WebViewList.shared.list[sender.title]!.configuration.preferences.javaScriptEnabled = true -// WebViewList.shared.list[sender.title]?.viewDidMoveToSuperview() -// } -// } -} diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index 3b1ba65..15e782b 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -11,9 +11,8 @@ import WebKit class BoxViewController: NSViewController { var boxView: BoxBaseContainerViewController! = BoxBaseContainerViewController() - + var gradientLayer: CAGradientLayer! let preferencesVC = PreferencesViewController() - let buttonHandler = BoxButtonHandler() weak var menubarVCDelegate: MenubarViewControllerDelegate? @@ -23,11 +22,31 @@ class BoxViewController: NSViewController { 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) { WebViewList.shared.list[sender.title]!.reload() @@ -52,7 +71,7 @@ extension BoxViewController { StorageConfig.shared.setPeriod(.period10s) } if event.keyCode == 2 { -// SdtorageConfig.shared.setThreshold(.percentage30) + // SdtorageConfig.shared.setThreshold(.percentage30) DispatchQueue.main.async { StorageConfig.shared.setThreshold(.percentage30) } diff --git a/Box42/Resources/Assets.xcassets/Icons/Contents.json b/Box42/Resources/Assets.xcassets/Icons/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/Contents.json new file mode 100644 index 0000000..e6da493 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "arrow.clockwise@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/arrow.clockwise@2x.png b/Box42/Resources/Assets.xcassets/Icons/arrow.clockwise.imageset/arrow.clockwise@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be10d0bdf05f8dcdd3fc35308000b79e2905d097 GIT binary patch literal 1114 zcmV-g1f~0lP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91BcKBS1ONa40RR91F8}}l0DVlZrT_o~#7RU!R9Fe^msyC7VHn3T#x|C0 z8DkmQqmZ&>Y^9kig_H|~Y#~>2As0eiC^wemiXx?y$XYWomd0B4HM<%jLdG6`|1;m) zJm))ezVDp#nR9MD^*hh=yvy@G=Y8Mrd*3gwQ8XDx_f^mg?net1z4rw|Jn)zkHC$fA z08{AS$%`=_{Q+)ze%dN(GF6ON2Cco3C!pWKZO>0jMNQ@-qn(0MunE1vzXLgu9*lY# z-2TyKo}QCTyg|F8Z9@0(r>2uolx1qdKwY5-3gI^#2ko1-&=@Ac3wQ{j(loS1e1l=Q z+OVUcAL#w!mv5#(32y==dd!s9YbyIN(d_9FUIe|v8Yij$PWeQ5pQJuk95yqWiS;lb zAc$t-C$xlQ@$#u_0fCaNvpOw=6=3((AN;FO;pr#nFW^K84TtT}$`ztFL$&c!Hnq;{ zz&)l;D`40%b)d}=UtcY6#_FWv-DX4y?FW3S6_CX!II-O5? zT5KXqQs|eoNgrx%nScke3zD|3t56~*z$UV^t~xVoj|o_X-8qFYYID-`Q$ov9=oi>z zj4xnmVC%Zd{l0#Y648?*nP017znAzeH-3<*rFF6uV~2Ax)tc(N;MTk(jX-6z-37DK z=o8pfN4-m=5<8V6A~0a4m0BkI4mpRfw`@*C$@DcNUpIEvO`T2M%&5DAP52D_lfrr&z$w+qBs@U%Yel>*+DXUFzeR*D#?~=U2~9P#LVanx}oEbvwQz*n;6pkS}Tik4s?lz`Vy4T gfB8QH4L$>Z0fK|Kq4O9|&j0`b07*qoM6N<$f**nGw*UYD literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json new file mode 100644 index 0000000..4b93ed1 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/arrow.left.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "arrow.left@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..dd616af1f5c6826b7870cbe94f4db32f123b6b38 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0vp^DnKm9!3HE<9_|SSQjEnx?oJHr&dIz4iKRw(ruq6Z zXaU(A42G$TlC0TWzSWdSpsEeBF~aK7_x1_ma6PZ!6K z2+qCJeYIU3C64P~_ZHfAZ+n>2rVU5j;=-nRT@SNs%2$~0v}VfM)}x}6TBkgT4ZG)+ zr0n|fckwd6?K_Xp%zkF~b@%x>#^-I$|35c#W^uk*@GMi~9JyT&IQAXr4xKt->0HCp z7o>V?kFR%mTff`uI8SSm$)0nD?nyhk6=u&!-n3pVtl*80_6fCTEm504Jc}?k+@rMd z`}WIf&*rR?tnf6vr}<>PJtugFe0+oK?AvZyV?J4CnVFzX$MNF6;7R@GOGJsNW_EdIdp>#y(~F4mO^3pL&z z5xiho$l!QZ&4cyqW8-YE?`)2{bECxs%ia^_oKb z7v&|glvJE5$*7vUbpDz?`Q#(7Yq#?~v)`A@RsF+Uo-0cib literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/Contents.json new file mode 100644 index 0000000..483e2db --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "arrow.right@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/arrow.right@2x.png b/Box42/Resources/Assets.xcassets/Icons/arrow.right.imageset/arrow.right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f3362b8c3974b221da2e324d79b487f0626e1de8 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^DnKm9!3HE<9_|SSQjEnx?oJHr&dIz4iKRw(ruq6Z zXaU(A42G$TlC0TWzSWdSpsEeBF~aK7_xpt8rFE{-7) zoM)%+^kR0DX%BB^x#%Y7x<@NeBzLR8L5*8n+x9giB&+^lna5$*#Q%VC+Ck=xLb-cB z=&jAUqSku+JNM=dZAZ?YI`{71!_zV|&(!>UpO!Yc=up4mvN>)16`b|I5{%0X{;=ge z6fzRf&|>cWCO;>w!#Z8`D=&x2)KBrs7dpb-t~>7kIpx`WhSWDVzx<7C(Oq)1Z=qn- zRRt!`n*x)LD4IC)Ym`V%U1?p>G%3;BgImr)x@5KE6xGz=7t)=z8SQ!jJA%Gn=}tSf zYyykQ)YhsO%&kj~EnG1rSCP}>)rl$0uM}cdvcKy8Dfd~Zb;9m@nxeVfhXWYjJ^igJ zx>SJg=iO+g#S6B2r*(Z->U9jWX3w4RNNS7jli=%KmaJP}ZIGCM=I=Yl=tDdj-dua_ zmuK%}pF5%D#L0DX9@2vj5ENnX0!orlfVWa=)K>v?#Ttq($=9mo4W*s@3i; z+s9yKRipeyWZQ;C;c4AvH;wjf`!BITwp{kh4lDk~{U7*aLoy%#nILNeigr&|KbLh* G2~7YBh5MEO literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/Contents.json new file mode 100644 index 0000000..97e4fcf --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "doc.on.doc@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/doc.on.doc@2x.png b/Box42/Resources/Assets.xcassets/Icons/doc.on.doc.imageset/doc.on.doc@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5a880b3a0033eb8c28d3e273eee5429edaee9b31 GIT binary patch literal 1301 zcmV+w1?u{VP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91D4+uX1ONa40RR91F#rGn02daMUjP6Ee@R3^R9Fe^m|3V*WfaHnZBi>T z$R=zMy;6##%@a{X6a@thK9!mEBn9~pR8ZkV^$_%s(P)-fQnvx=rQyMc$R2#Dl!|N) z8$d!ci?THP{Z9M4t+UTL`|Q2Xxg8%|@ZaBBYp-v8|NV`7@8O|pGL`V#!6o333RS-( zb~P9UyDHQh8mT%k@rbUlvSz%Th5o$M+EUn9w!T%td)cjtV0b0UuYgYzTw zMW8gvP`9Hxn>(8Vo<={uV|4S4$3nf7;}v{|Hixyh_G|BM@y-pNpU|C$n}e^c`dt=y z3gt7P>pU(?@QA=*1N!g5uA(j>*dbO<16A{F zNtxYJlqJ|wu?L5XLz2!%rZ`*PI(i zf!OUQWB&@26Tl5%8~6bH0P2YKCHXv<0nP)DgT>%a(2%qby5#QxSAn=^HG&E*d${)& zSPDALO}80O9_2FdjY^Oy=pF#mGT%Ftw}QX49b$WN1-KeiAxC)QB)XjPMR25!8sfIK z0DPO(y^wMlXmF9-HDDe{BJ+)4dvfH;W3gxDeABU40UNTxPGWoQWDCw4!3)3x;9_t$ zxZes_fF$3e+ycH%jyC1B_#VvsUr|m2j)Wvv0vp;2lEgjpUYtIBC)vOa2`WD98VR1H zmC2)&MdVUkD%YX7k4adPGr>wA$uuV=bR|&E$dLs8p|!Kn+rAKlm=<+B3EG&4 zzh`lhb5XQQFV0>Gx}|iJWduAKf-XQ`66`{?^pk`vJA-bIoDZTe+#XZkMRP?PuXxfp zPq%3lNgaZphJ+*N&j!1!I)T8`z}jvV>I|_P?i<|_m$-jiiJ0<}HJ9uT>~+8)^UN(X z7YS<|fxe(B2mM9tV+tQ_3g;EbyXNap1>N$2F!Ct#?Uk}#k!NWtH zoqJ;srqf2ATkCE!;UW8``o4G_SQs*XI7otvAhI}+kzjsre0h)rZM*1Gz*n`6gCrO_ zZ%q9g?PK64!rOWWNzm`<*Cm1M0sev50)7KyGDw2{!?CvtWpCVOnh56!=2uZua374A z-(l@45{!SJj_z8cw}4|p_1JE3H>(o-F}TuSsNm|GIzpz|AzN%WxSLfM$$Bt7bI+&r zP1n`6J@fTi97uv$z~8#*$I&kI_d!>2PRsxjGSUAfqcoI$G8MMz6Zz@48C(R?6QYir zIAV7Kd$Fs;Rpo!V>w*7KTr7SX#`~DH#M8m)@)>v&_(kY9O)2>YZAhy(!^vU#00000 LNkvXXu0mjf*TPJ; literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/Contents.json new file mode 100644 index 0000000..849e448 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ellipsis@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/ellipsis@2x.png b/Box42/Resources/Assets.xcassets/Icons/ellipsis.imageset/ellipsis@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e027e56412dc5da67a7faf1a845a0635d55048bd GIT binary patch literal 459 zcmeAS@N?(olHy`uVBq!ia0vp^szA)a!3HGj)|kBpQjEnx?oJHr&dIz4a$Hg)JkxxA z8MHvE7#Q0#8CXC{fLIEM85o!sFfuR$X-1IP0w%bu>H=msn**e9<;+*RfXYlgT^vI! z1m{k%_jU@DIJR}g!jo*qQ|y|XuLzjEn4ZD4(qBQZ*D*Vn&(eZLQsW0_jFx+}66c&l z7X{j<1(|&KKH<>Qf_K_K4!ytk+3tMp`T5o7cV0YEe`H7O0Y#sMyrvR|SDpBDK=X~W z{JV$DVMq1&=QJOibCBESfXXRVK3)$;gIy}=AEZU*ZWAkdnNk15HN&#Xz<0tGMM;s& z{f>!~Pm9VlN^4!=vRb$C#MMMrGnx3GhA(_q-xI&yA=$rh``^WUpX7=)pHAaF|ChzL z`%~*S=UeGICadqyQQMj-lE41t$}_7>k6&35*V}m5Zm!pwU7Y`RUtAx0`{I(kgWG4e zzbJP*Zo4O~Bi`*l-$#}9Udsckv;2D=aF+b~<{*6Kq~<~Kh>ty%ZOk_s{dY9FZ*bzi grti>xRJPcHeYTs0g%oS?Sx`WFy85}Sb4q9e01lL^;Q#;t literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/Contents.json new file mode 100644 index 0000000..99f8ebe --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "figure.skating@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/figure.skating@2x.png b/Box42/Resources/Assets.xcassets/Icons/figure.skating.imageset/figure.skating@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ddfa0f5d0e4fdc5b728177e6e5c2fbd05bbacdf GIT binary patch literal 1333 zcmV-51Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91C7=TU1ONa40RR91F#rGn00pQpO#lD{pGibPR9Fe^m}`iZMHI)^)eucX zlhyUoW@3aF)TI)Iq%tLX3os}wkj)DS`mI6)IcXV z4xhmhXb~yrQ&&NwLp}Wo5EKn8N?s=L3!dO@&@F`?9$QIOWKu7NJ`{ah@FiS$Qr%OM zlBq@B)X9vbg7zY(Z(~YQm$7{lvbPQy?t)&s>`{2aiFK9!eAw^k|L>}f6fLS#XLXWF{6Wo|?8LV9Q}T>n+6y+AmrC znC9y-PN6sTCWE_L0W@uI!Iea(HKw#V-k#Z;^BYkrNgE-~0+eZH=4OsFI% zpw6hhptW@oBzm(Sg4SF}&S7{Bbm&S>!9aLSod{`)t>`A!Fd7?7C-9tuev4!4K>ro! z1!{23KP(o`eG~igsfc^q3PO(RuOj6paPezQY z$7ff-PiyFUz?NIB`qP-8;@B=DLKp0t6Mr+#JU>An+B_LyZ<-ZgE$B3t^Z`}sTDSzR z^h0q1zJoFFFxb+QjtcAdwlZ&9NsR;rGt!NQZi+iV71qcjG`<2=js+=vp>PTT`Z zSW~G)JAo0kD`Bfq#6A_=m6<4JyGo~jnEqtAYU#Vu{uK1J%7{wDV952hG##$2M=>Al z543%*(OKxRYXeLN)hi>4uicnSd`T&Q*21fx=59-{aMD&aC4$wW`oVzq{6<@~s z@j_=-chK)jx_4AmR|XF-em zuFK~{Y=nJK85zAVeuqHg)<%vgxy9@(P1&F%s21_#NjvK?00;AihGaS0_Lw!IU80+# r659#yLCh}v6+f-Vj<6CMAWCik2kOHm^(~4k00000NkvXXu0mjfKUZ9v literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/Contents.json new file mode 100644 index 0000000..f437f7e --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "figure.snowboarding@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/figure.snowboarding@2x.png b/Box42/Resources/Assets.xcassets/Icons/figure.snowboarding.imageset/figure.snowboarding@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d7972331cb9541497de78c2b7e97830fb679906c GIT binary patch literal 1277 zcmVPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91E1&}a1ONa40RR91CjbBd0IMvj`2YX}XGugsR9Fekn0cs=Ss2HE7>2Rs z;ud0Dw@?a0WQmZa8DvYAvTMR$l%niJNY?nzKm0SMhLAN`Q{s<%NA@*|Nh8bD*tgG@ zd)#x+J@0bfD?IhN?|Gi{oO7P{yw6#Fw^HuwNiT*P1o?0W{(y_{-N|Aiy6SKleH5gY zN*>QD*lK(1w&?|mNFxJrS{vc`7Q5HD=Zm#EH8x93f4F7|XcNF>?#d#{7 z7Qti3?p57Ey-to%X)*&QK~<+tssh~v+d#ocmcZzbrP4oo3E8!UrIIYcnvM%7D95`S zgY&$Oz7)=u*n9KT%5MmFUb zhJ&d;1QWqtBdB3gp~eg~9@3mb)$r>9T4+j-`w%P@NrPsLrY$SYzU&63)L01*-HJFp z>&)sUx4_SFoyXL*qE27rC0qb)k%^KuSbctXEAkDdJ$E)V0Qbd$QzJ{T8gwK0_E^lH zMHihZa0&F;ufQ+hUXto#(}ALXi{Ke}B{W!l{>|XdlCSeM7>`>Owy2I1PHqa-TxBI9Wucdk1#?*I_v78YA?Z*p(VeuXf;0UTbW1 z;W*?%Pq3s#r9SuTPk=nfSHC25(rFf5DKrN6O^iM2`5P5^QI#e3E_BB(13`hRQPyC4({_M5uw*;s zOO~#pW`CArD?-<)6)aiOpa!Gt2m3!M+B%G2BJp;@E=JEWw_)M$oEWX6bfOJA)A| zx`mK*KQR8@XO^7(k)9?)9%xI_#Uo0FQPBYo!>K5z5c?RMwPDu@Y4jC+n=_WaUN_C` zIZ&XFU?=~&1p1mM6|5G_3aAI)t7r$AX>wLGI|Q`d6oT}u_Xe6) nNObRb1-gu10qr)*`8OW`GFrqIvIRX%00000NkvXXu0mjf87n^L literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/Contents.json new file mode 100644 index 0000000..faa8a6b --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "figure.surfing@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/figure.surfing@2x.png b/Box42/Resources/Assets.xcassets/Icons/figure.surfing.imageset/figure.surfing@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e6b0e9172603b167b50a3551a52b1d81239b6c8 GIT binary patch literal 1570 zcmV+-2Hp9IP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91E}#Pd1ONa40RR91F8}}l0B`aQv;Y7Fj7da6RA>dwn0xG(Qyj;CsEFuF zl*X1QS!$N#x{%vgi8eI$bDPn$*+Pk_t+_2V%B7H*85=egnGJvB(p*NRNz%-^p^!>Z z!t2$3XC0@f-}8K*=le77?X~Be&-py(e9n2!?fY$LsIN|;y0_sgm;(F2|5~kx?shQX z_)vz|BypXAC;3H{e0<=w9+ev;JEQ{<0{1Ehy zYzs(_hYgXfP_pbCY)|cz;k=Ai97U(ir%_o)(sSXk$QF_-NL&Vg1VfSMzD1l8A4kq0 zvVxwEeHg?+lWk~(te`FH1tUz3{uq%h%!uxMY_G%F8D$@5*kaR1ai&OmzambFkBevy{0dHicxO70 z{Ke1>3}!nh_x4MmotZ=~&Pm`-R9IyK50x(_@fP$0_vKi}lQB>aq&4t6yaVp_b}Hyy z5@TR?lu%BZDD&eoOjJ z@GI3tRi;WBfTQQMIW8?A-x1ua-F@8S|AI=Y=ZL!(KL>erF2m;z_!>&9UL)>qF&hpk z5XqtVj06v@Mc_K9S@jBh5-sPQj&X3ddn%j;pMYCyO{z!W=g{KVnp)lMd<4nM!E3_O z-RAsM-h9lfp%V_CmYs7Poff0OJ$xc`fK&$Wz8~`qc@MljR5kD!)HrmHTK6<{qA=Zl!T&T-+O~1U{S!9)vtC!Ql!>k96W*<7xKOk1FJ;-Mc zZrQ;5P+^`{;P7moQ&esz#4j1-ZPSxDbjY+{=7q9>|H;cmh{uHRy_g;hn1$K|Z;*X7WP_xPgZbRPq zro%upCFR!U{yweN_p1aR+B%)YSoAD*J(&k$L(#N>I|}cEb8|dA3h_vhZB|!PdS>F`AbghC zMw34_vE5BR?p#uwpEYQIPI(LS^Lcs|`C;JP{i5leFa=&BpDxf7uzi{M-ABH(LIbYs z58wbe3H%9mDYOSiZU{Xa;qN;ADf-paQE`ll02b?nZLYSYfff>*nipY5! z*S&zeJ6K)hh#Gt&II3+SRZk30LI}bRJPxjh=5!Z@;T@k<&Wh&R$t@dz$1@NI^9p(Q zXHVc%j;^Er8eEwcR>`{n%cvhOT@OPctP2`RfBIX{Lh44n z1K>n(f%gJCS5zx;yh!KtGZw9&te+z)Z$uT?nV#U+aIs5g=+K1cifgD1tb<+p2OM+? U#-r7d`2YX_07*qoM6N<$f(KU8s{jB1 literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/minus.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/minus.imageset/Contents.json new file mode 100644 index 0000000..c437350 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/minus.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "minus@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/minus.imageset/minus@2x.png b/Box42/Resources/Assets.xcassets/Icons/minus.imageset/minus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2a101f6b805c60f296c058b60618d675879606f0 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-l!3HGXyW3s?QjEnx?oJHr&dIz4a$Hg)JkxxA z8MJ_G4hF{dOa>N^5+IfWVg?501&j>LK$;OGwtxvPtFV9>&IajVm~s5IIgqmRba4#P z5KT@=NO-{hh(X~QYf@EHyu;}-W2R0~ha3<8*%ROVI>PcqLz(l!?32fNwtTb|n9Xb` fJvW!#^`I9+aTnVc(ZXx0AQL@Z{an^LB{Ts5$Hy>S literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/Contents.json new file mode 100644 index 0000000..ff506bf --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "pin.fill@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/pin.fill@2x.png b/Box42/Resources/Assets.xcassets/Icons/pin.fill.imageset/pin.fill@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..164fbcfda65f9c2ef0c2a6736acf1d5de29f6cbd GIT binary patch literal 890 zcmV-=1BLvFP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR919-spN1ONa40RR91F8}}l09F8|GXMYrpbGezFy}jL;yWLxx3>@?3&71ezd9(NC-2wlp37ab?u?;00gv4rFpIH|8 zOP?<=gnI-^<EiF3`%lP#bq&si)uPBHYM!sD0Go_K=VRy1#?>2v0mc2 z_8o$U@qp2Ps3&soCBC78QSH}&YlkjyloOBjWRCqjp#!3f589^zD}^|NpZJP>sN$A3 z$lOaFVFf!0eP;VIZ?&ydvYg`X1KgyzwsFpTEHQ<7oEKyG-MA(ZtPJHeHnJP%=a?FM zH;LD@9TaErBxy}5STEuO+@^d&j~)F2UZO|L;7^)eLy}32f)LWI{279Ai1#gSV8obQEekub?j=RMlC< zLDd5=x&gO-$bOhYWP$ww552DtSQN5C?RY~}SIkK5_+v4sC?#OcdycAD`586KdBnQC zmbsXlH#0Z))BP$>#1TenPu+Hb$5s0U=&`oKjlN=WKO0Gz9t&$G%s!J8%8LVhV*R|y zcdfQFDN`$o>X*PpMLN6|3nSJ+OK0pC@hU5*u-S5`bx7@nTHuHAYs*II7TN{BH?Ac@ z*(lvYdtixK4P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR919-spN1ONa40RR91F8}}l09F8|GXMYsL`g(JR9Fe^ms^NVQ546=Wn3CE zZl!T452BDr8I6aLNW2*o%8N(EliZ)=!Na5!MM?>UBBfm7$t@2qiQHaHNpdNk?{oH=v8yv(Zq?6uZj`@ha!XP>pdsjK@>(l5$86?-9Qi2S`Ze?ssKTm^qb z=830cp9KRnQ6o75Z@akrTY?t!S|(MhR{fC->>NseRSK8882jCkL!Zx@&9?5T>0Q*r zSkDbwao%ffMH3&)!yGp z7OVs>Y~fh+L1w$E$^`j_vI}eiUxU-fYKax6limh?$tcU0phTnlcQdD+P*KtnYoX3T zI1B1Ji95jm83fUJs47_!HyVSImRg?qg6caS5uBCAEQy`O$zx8hgs+L?N_I~ZdpTo5 ze<-g~9G5w1jYe%B(47r-h&?? zNa~K$63>RIC9pA0DZ^YPRel$BxHfPBB=+{u$bFIY$v`b{fs87mjux6rQrH`u`@rRR zGAZ#Ig0=(iJ}T#Ra1T5L@4zSU8>r-?z%(!iECLgO%O#8*Ks<@E4X@uYx3JfOhQ#P( zr#7S4a|$@udF+v(o9HI-z`fYRyG8ZPv4U__DDa*`AL0~xm%52Uzy_b}rLHgGj&bh^ zd^#N0Y+`GeC~%w$*OPJ%ZE%*7E(fcCqyuaOm2M!#Cx(YUiKZrWdV#gfRS!s#oV4Z5ed3-j_4gpI z2Vd%#H}QRA&eeDGCVoZYaH(IhhsdnzTFfgSSg4;#r}Gf}1unUl$)^gPz5oCK07*qo IM6N<$f{dfOf&c&j literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/plus.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/plus.imageset/Contents.json new file mode 100644 index 0000000..ace344d --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/plus.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "plus@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/plus.imageset/plus@2x.png b/Box42/Resources/Assets.xcassets/Icons/plus.imageset/plus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3b9f6216ee1a78dfcbed2c3cbd99402d1d67b79c GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZp6?&Um^whD2~C zCn(5AFl>!ud^Fo(j@vpzpC?%?uRb#+g{}CfP;_?T5yl*kX-bEzRbC3TtBt6RbokqM PApd!~`njxgN@xNA^=WS< literal 0 HcmV?d00001 diff --git a/Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/Contents.json b/Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/Contents.json new file mode 100644 index 0000000..e79e1f2 --- /dev/null +++ b/Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "shippingbox@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/shippingbox@2x.png b/Box42/Resources/Assets.xcassets/Icons/shippingbox.imageset/shippingbox@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0a5b3b044dc1c370cf0b1d103f45bdbae75c15 GIT binary patch literal 1530 zcmVPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91C!hlW1ONa40RR91D*ylh0Q^4WJyFpR9Fe^n0ttoMHq)Q%XSqj z%A~YHx@l^KnnGYm*WL1hWmy|h(Pg#NFr_6GB#OMHB_^rh9~PFE3<@l}SXfHvAKAsq zjkMUx)?&MvyP|e`p6$#s=i76>J$tGB#~(a9Gw;kd^L{h$%r|E{c4!-&M>m&2PpE^B zVGA6F7OP{6pZxd1z9bL9upIr=U|R~S;m;iPO`2NjTz7h&0%PHrCPvvq{akpjiFS>u zo9kR>dbkrNKv#(M83j2BT;gJgwUvTSei<9n^38Fsl#VK(SE57XYaV1Oac%$)&w#;+PWDk=02|=%L|rJJNyeBg35HC%pY$161xGTrMoF4; zJ!m}@#z3;2yKo{D8b?EEJ01E#tSSogVN+}j`A#7drA6djl0|SKBpt)l!RJOpA27~- zgEZ}>@CiTb7^`ujw zyM`21Qa2m6gI|<;py9kSALMR)6h_0=U?e>jZilxrspT~NMdeH268lUp{e*EA_!2sn zrEr*L88e05q<6!3h?nz3$}{0rxB}ATjM?_eM57~=SHLykX7WWEDb2aicr%%i@Hluj z1@$Jg6jnkXh;=-L3E+&~2=O?^l`&;}AAr1yAIjT^3ghiLaEYFW_zQ3;<(J_xaHf2b z*Wp3v0zt-=Vc|yjCK%Jwc(;ZPk=8!colC~uI4l@4sZPh6NV9RZ2>c4=Tt4ivQa420 zFkgN*6~<#Zd=)i{9gE{?9c>D6Eb1yd7P2Y|EWAs*5RdT}Kzl)Pl{QYHF_+edOKCjD zakL^)PJ2FYU0XPpxAWFk9CfaxGkA37S~GK=N2)V)tIxIXpK$H3|K?RkzDyzSSEIdj z0RxwW!Hv1ip+I^Ytb%@#?f=LYGsqC6U z@HV6T-7-t(yawG0uR)OZvEY?wJcNhHwwVUfli%D0a9Y&sKJxd%2Axpee!b#&rP&2R zPO;bQjc{!+wleL>^H0JWxG3t&Z}So;g)Q2HbLQ1{xB+HD4FvTf>WP)Ft|aGL$S5M&UK0SCJuiXfkcP~pqCxlWB5?IrIlmch=*o|SFRnPvcc z`}JQBv8pL7gmO4PQ!#^dIJi`?YAGy-l@PB8#l~umb3SeRkuVKTheG8o*yG8#tts@O z<~kSpbt&%xXRA0E^Q7Cb&wDaPU;cPEB*=VV?2IWDOYo@u_m z3|c@o2Loe!CIbsd2@p#GF#`kh0!9XAAk7F8TfhXD)my*}XRCk|N+{VZWnf?u_H=O! ziQs%Y(^|*HQKYThmP^#pL&Rl`%a_$xE^y8L+7+&0$~CvmY0;G+B|(?P3zi8@Z3 zZQNnEL2pKDQmD-~@hxW$tZFeoBqrjhcSBn#Sjd{g?Thq3wl@b%YtpB(h&OY~X;kmq z{eyoa*S_0)cLM|rbPnn!X(CcUKR%w=Jxy(T!O?HbPpZ@Zzk3>z=kH_@s+T#tIlbdb%*sVC zYtAh6+5CE?^0cjK(+k!Ht0@Qu75Ui~UA*)}Xx$94s6*br%k`I6RmyA$+y1uc6jO$; z%*vfXuG((BTJbY4J%6&=!R&U-p{>VfH@SH9v>iU->OI+eN7AixmD!fRi=MTnTQC1) zJMaC+_-_t&p>;O{C3pMSuDcwNoO@o;#M6C(8oaZ?>4+%{*n_aBIQF{-Ea# zyA$jK1pKt$EVj=5`s&i6nX5C*udz8_)8+rte0Bq0YuJJGaM|1X8*eSU>!kg|?o@`n z0srl9o}t3L%nL4SEp4oo@G>>J{9xghtMQtr3s^Rm7tQxxcqDvL4=9; Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(goBackWebView) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func goBackWebView() { + callback?() + } +} diff --git a/Box42/Toolbar/View/GoForwardInToolbar.swift b/Box42/Toolbar/View/GoForwardInToolbar.swift new file mode 100644 index 0000000..e5f04fb --- /dev/null +++ b/Box42/Toolbar/View/GoForwardInToolbar.swift @@ -0,0 +1,31 @@ +// +// GoForwardInToolbar.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit + +class GoForwardInToolbar: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(goForwardWebView) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func goForwardWebView() { + callback?() + } +} diff --git a/Box42/Toolbar/View/GoHomePageViaToolbar().swift b/Box42/Toolbar/View/GoHomePageViaToolbar().swift new file mode 100644 index 0000000..2728ff3 --- /dev/null +++ b/Box42/Toolbar/View/GoHomePageViaToolbar().swift @@ -0,0 +1,31 @@ +// +// GoHomePageViaToolbar.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit + +class GoHomePageViaToolbar: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(goToHomePageWebView) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func goToHomePageWebView() { + callback?() + } +} diff --git a/Box42/Toolbar/View/RefreshPageViaToolbar.swift b/Box42/Toolbar/View/RefreshPageViaToolbar.swift new file mode 100644 index 0000000..8be72bc --- /dev/null +++ b/Box42/Toolbar/View/RefreshPageViaToolbar.swift @@ -0,0 +1,31 @@ +// +// ReloadPageViaToolbar.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit + +class ReloadPageViaToolbar: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(reloadWebView) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func reloadWebView() { + callback?() + } +} diff --git a/Box42/Toolbar/View/SideBarLeading.swift b/Box42/Toolbar/View/SideBarLeading.swift new file mode 100644 index 0000000..9849a05 --- /dev/null +++ b/Box42/Toolbar/View/SideBarLeading.swift @@ -0,0 +1,31 @@ +// +// SideBarLeading.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit + +class SideBarLeading: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(sideBarLeading) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func sideBarLeading() { + callback?() + } +} diff --git a/Box42/UI/BackGroundView.swift b/Box42/UI/BackGroundView.swift deleted file mode 100644 index de430ed..0000000 --- a/Box42/UI/BackGroundView.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// GradientView.swift -// Box42 -// -// Created by Chanhee Kim on 8/18/23. -// - -import Cocoa - -// MARK: - BackGround Gradient -//layer caching 기법. -//레이어 캐싱: 복잡한 그래픽 연산이 필요한 뷰의 경우 wantsLayer를 true로 설정하고 shouldRasterize 속성을 true로 설정하여 렌더링 결과를 캐시할 수 있습니다. 하지만 이를 과도하게 사용하면 메모리 사용량이 증가할 수 있으므로 주의가 필요합니다. - -class BackGroundView: NSView { - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - self.setupLayerCaching() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - self.setupLayerCaching() - } - - private func setupLayerCaching() { - self.wantsLayer = true - self.layer?.shouldRasterize = true - self.layer?.rasterizationScale = self.window?.backingScaleFactor ?? 1.0 - } - - override func draw(_ dirtyRect: NSRect) { - super.draw(dirtyRect) - - let startingColor = NSColor(red: 1.0, green: 0.804, blue: 0.0, alpha: 0.9) - let endingColor = NSColor(red: 1.0, green: 0.447, blue: 0.0, alpha: 0.7) - let gradient = NSGradient(starting: startingColor, ending: endingColor) - gradient?.draw(in: self.bounds, angle: 90) - } -} - diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index caa3aca..8ce6c4c 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -7,50 +7,121 @@ import Cocoa -class BoxWindowController: NSWindowController { - var windowInstance: NSWindow! - var gradientView: NSView! - +class BoxWindowController: NSWindowController, NSToolbarDelegate { + override init(window: NSWindow?) { let contentRect = BoxSizeManager.shared.boxViewSizeNSRect - let styleMask: NSWindow.StyleMask = [.resizable] // [.titled, .closable, .miniaturizable] - windowInstance = NSWindow(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) + 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.styleMask.insert(.resizable) windowInstance.isReleasedWhenClosed = false - windowInstance.isOpaque = false - windowInstance.isMovableByWindowBackground = true - - super.init(window: windowInstance) - windowInstance.isOpaque = false windowInstance.backgroundColor = .clear + windowInstance.isMovableByWindowBackground = true - gradientView = BackGroundView(frame: contentRect) - let boxViewController = BoxViewController(nibName: nil, bundle: nil) windowInstance.contentViewController = boxViewController - windowInstance.contentView?.addSubview(gradientView, positioned: .below, relativeTo: nil) - gradientView.translatesAutoresizingMaskIntoConstraints = false - gradientViewAutoLayout() + + super.init(window: windowInstance) + + setupToolbar() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - override func windowDidLoad() { - super.windowDidLoad() + // MARK: - Toolbar + + 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 gradientViewAutoLayout() { - if let contentView = windowInstance.contentView { - NSLayoutConstraint.activate([ - gradientView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), - gradientView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - gradientView.topAnchor.constraint(equalTo: contentView.topAnchor), - gradientView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) - ]) + 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() { + WebViewList.shared.hostingWebView?.goBack() + } + + @objc func goFowardAction() { + WebViewList.shared.hostingWebView?.goForward() + } + + @objc func reloadPageAction() { + WebViewList.shared.hostingWebView?.reload() + } + + @objc func goToHomeAction() { + if let item = WebViewList.shared.hostingWebView?.backForwardList.backList.first { + WebViewList.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") } From fcbb4f695ac14e4bc3bc14e359231339bc6ded39 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Sat, 19 Aug 2023 04:21:06 +0900 Subject: [PATCH 41/55] =?UTF-8?q?fix(webview):=20=EB=B3=B5=EC=82=AC=20?= =?UTF-8?q?=EB=B6=99=EC=97=AC=EB=84=A3=EA=B8=B0=20edit=20menu=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Resources/Main.storyboard | 319 ++++++++++++++++++++++++++ Box42/WebView/WebViewController.swift | 39 +--- Box42/WebView/WebViewList.swift | 3 + 3 files changed, 333 insertions(+), 28 deletions(-) diff --git a/Box42/Resources/Main.storyboard b/Box42/Resources/Main.storyboard index 0fece80..a34efc7 100644 --- a/Box42/Resources/Main.storyboard +++ b/Box42/Resources/Main.storyboard @@ -148,6 +148,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index ac3eddb..3b73e89 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -44,6 +44,7 @@ class WebViewController: NSViewController { } func webViewInit() { + WebViewList.shared.hostingWebView = self.webView DispatchQueue.main.async { self.webView.load(self.URLVM.requestURL(self.URLVM.safeURL())) } @@ -59,8 +60,12 @@ class WebViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() + if let scrollView = webView.enclosingScrollView { + scrollView.verticalScroller = CustomScroller() + scrollView.horizontalScroller = CustomScroller() + } } - + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { print(message.name) } @@ -70,32 +75,10 @@ extension WebViewController { override func keyDown(with event: NSEvent) { print(event.keyCode) - if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅊ") { - // 복사 동작 처리 - webView.evaluateJavaScript("document.execCommand('copy')") { (_, error) in - if let error = error { - print("Copy error: \(error)") - } else { - print("Copy success") - } - } - } else if (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "v") || - (event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "ㅍ") { - // 붙여넣기 동작 처리 - let pasteboard = NSPasteboard.general - if let pasteString = pasteboard.string(forType: .string) { - let escapedPasteString = pasteString.escapedForJavaScript - webView.evaluateJavaScript("document.execCommand('insertText', false, '\(escapedPasteString)')") { (_, error) in - if let error = error { - print("Paste error: \(error)") - } else { - print("Paste success") - } - } - } - } else { - super.keyDown(with: event) // 기본 키 이벤트 처리 - } + // 키보드 이벤트 처리 + // if (event) { + // } else { + // super.keyDown(with: event) // 기본 키 이벤트 처리 + // } } } diff --git a/Box42/WebView/WebViewList.swift b/Box42/WebView/WebViewList.swift index e4535fc..b5dbe13 100644 --- a/Box42/WebView/WebViewList.swift +++ b/Box42/WebView/WebViewList.swift @@ -12,6 +12,9 @@ typealias WebViewMapping = [String : WKWebView] class WebViewList { static let shared = WebViewList() + var hostingname: String? + var hostingWebView: WKWebView? + var list: WebViewMapping! private init() { From d2df021ee56cd542b0d9cf8d8cc52650f7ddbea0 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Sun, 20 Aug 2023 20:45:35 +0900 Subject: [PATCH 42/55] =?UTF-8?q?test:=20swift.yml=20=F0=9F=9B=A0=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: swift.yml 🛠 * refactor: 세부브랜치 추가 🛠 * fix: os, version 수정 🛠 * fix: os, version 수정 🛠 * fix: os 추가 🛠 * fix: set-upactions/version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: actions/set-up version 수정 🛠 * fix: 우분투 버전 수정 🛠 * test: 정상적인 build 확인을 위한 Package.swift 추가 * fix: build 테스트를 진행합니다. 🛠 * fix: setup-swift * fix: unbuntu 환경을 삭제합니다. 🛠 * refactor(yml): 중복된 부분을 제거하고 build만 진행합니다. * fix: 🛠 * fix: macos-latest🛠 * refactor(swift): xcode버전과 sdk를 고정시킵니다. * fix: macos-lastest로 관리합니다. 🛠 * fix: 🧩 * fix: macos-11 🖥 * fix: xcode 버전 12.4 및 SDK 고정 🛠 * fix: build test 🛠 --- .github/workflows/swift.yml | 40 +++++++++++++++++++++++++++++++++++++ Package.swift | 28 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 .github/workflows/swift.yml create mode 100644 Package.swift diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml new file mode 100644 index 0000000..668423e --- /dev/null +++ b/.github/workflows/swift.yml @@ -0,0 +1,40 @@ +# Author by chanhihi +# Date 2023.08.09 + +name: Swift Build + +on: + push: + branches: [ "feat/*", "fix/*", "refactor/*", "cluster_main", "main" ] + pull_request: + branches: [ "cluster_develop" ] + +jobs: + build: + name: Swift 5.3 on macOS 11 + runs-on: macos-11 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set Xcode version + run: + sudo xcode-select -s '/Applications/Xcode_12.4.0.app/Contents/Developer' + + - name: Set SDK version + run: + echo 'SDKROOT=/Applications/Xcode_12.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk' >> $GITHUB_ENV + + - name: setup-swift + uses: swift-actions/setup-swift@v1 + with: + swift-version: 5.3 + + - name: Build + run: | + mkdir Sources && + mv Box42 Sources/Box42 && + swift build + +# This workflow will build a Swift project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..32e0316 --- /dev/null +++ b/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Box42", + platforms: [ + .macOS(.v10_15), + ], + products: [ + .library( + name: "Box42", + targets: ["Box42"]), + ], + dependencies: [ + .package(url: "https://github.com/SnapKit/SnapKit", from: "5.6.0"), + ], + targets: [ + .target( + name: "Box42", + dependencies: ["SnapKit"], + resources: [.process("Box42/Resources/Assets.xcassets"), + .process("Box42/Resources/Main.storyboard"), + .process("Box42/Resources/sh/*.sh")] + ), + ] +) From 0519a4499a7c88e8a7ddb0658c81aa464fc6aa80 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 03:57:44 +0900 Subject: [PATCH 43/55] =?UTF-8?q?refactor:=20Resources=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Resources/Info.plist | 5 + Box42/Resources/Main.storyboard | 110 +++++++++--------- .../sh/brewInGoinfre.sh | 0 Box42/{Scripts => Resources}/sh/cleanCache.sh | 0 .../sh/exportMacOSInfo.sh | 0 .../sh/importMacOSInfo.sh | 0 Box42/{Scripts => Resources}/sh/keyMapping.sh | 0 .../{Scripts => Resources}/sh/nodeInstall.sh | 0 8 files changed, 60 insertions(+), 55 deletions(-) rename Box42/{Scripts => Resources}/sh/brewInGoinfre.sh (100%) rename Box42/{Scripts => Resources}/sh/cleanCache.sh (100%) rename Box42/{Scripts => Resources}/sh/exportMacOSInfo.sh (100%) rename Box42/{Scripts => Resources}/sh/importMacOSInfo.sh (100%) rename Box42/{Scripts => Resources}/sh/keyMapping.sh (100%) rename Box42/{Scripts => Resources}/sh/nodeInstall.sh (100%) diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist index b61be39..1520f65 100644 --- a/Box42/Resources/Info.plist +++ b/Box42/Resources/Info.plist @@ -2,6 +2,11 @@ + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable diff --git a/Box42/Resources/Main.storyboard b/Box42/Resources/Main.storyboard index a34efc7..f542723 100644 --- a/Box42/Resources/Main.storyboard +++ b/Box42/Resources/Main.storyboard @@ -78,24 +78,36 @@ - + + + + - + + + + + + + + + + - + - + @@ -106,7 +118,7 @@ - + @@ -132,60 +144,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -248,6 +210,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Box42/Scripts/sh/brewInGoinfre.sh b/Box42/Resources/sh/brewInGoinfre.sh similarity index 100% rename from Box42/Scripts/sh/brewInGoinfre.sh rename to Box42/Resources/sh/brewInGoinfre.sh diff --git a/Box42/Scripts/sh/cleanCache.sh b/Box42/Resources/sh/cleanCache.sh similarity index 100% rename from Box42/Scripts/sh/cleanCache.sh rename to Box42/Resources/sh/cleanCache.sh diff --git a/Box42/Scripts/sh/exportMacOSInfo.sh b/Box42/Resources/sh/exportMacOSInfo.sh similarity index 100% rename from Box42/Scripts/sh/exportMacOSInfo.sh rename to Box42/Resources/sh/exportMacOSInfo.sh diff --git a/Box42/Scripts/sh/importMacOSInfo.sh b/Box42/Resources/sh/importMacOSInfo.sh similarity index 100% rename from Box42/Scripts/sh/importMacOSInfo.sh rename to Box42/Resources/sh/importMacOSInfo.sh diff --git a/Box42/Scripts/sh/keyMapping.sh b/Box42/Resources/sh/keyMapping.sh similarity index 100% rename from Box42/Scripts/sh/keyMapping.sh rename to Box42/Resources/sh/keyMapping.sh diff --git a/Box42/Scripts/sh/nodeInstall.sh b/Box42/Resources/sh/nodeInstall.sh similarity index 100% rename from Box42/Scripts/sh/nodeInstall.sh rename to Box42/Resources/sh/nodeInstall.sh From 58dde9db27c903adeda3320cb037c1f85b46c3e4 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 03:58:41 +0900 Subject: [PATCH 44/55] chore: xcode.proj --- Box42.xcodeproj/project.pbxproj | 93 ++++++++++++++----- .../xcshareddata/xcschemes/Box42.xcscheme | 78 ++++++++++++++++ 2 files changed, 147 insertions(+), 24 deletions(-) create mode 100644 Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 89f0ba3..54be299 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -17,11 +17,10 @@ DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEC2A509B2600FF0AA3 /* URLModel.swift */; }; DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */; }; DE018BF32A509B3300FF0AA3 /* MenubarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */; }; - DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE018BF52A509B3600FF0AA3 /* MenubarView.swift */; }; DE018C032A509B5D00FF0AA3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE018C022A509B5D00FF0AA3 /* Main.storyboard */; }; DE0A915D2A8E348D00D1D6F1 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = DE0A915C2A8E348D00D1D6F1 /* SnapKit */; }; DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91622A8E6A5400D1D6F1 /* Constants.swift */; }; - DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */; }; + DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91662A8E6CA700D1D6F1 /* WebViewManager.swift */; }; DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */; }; DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91772A8F014F00D1D6F1 /* WebView.swift */; }; DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */; }; @@ -32,7 +31,6 @@ DE0A918D2A8F88BC00D1D6F1 /* GoBackInToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */; }; DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */; }; DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91972A8F977F00D1D6F1 /* ToolbarViewController.swift */; }; - DE0A91A22A8FAC3F00D1D6F1 /* WebView+CustomScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */; }; DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */; }; DE1F1A142A8B506600A88DD8 /* importMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A112A8B506600A88DD8 /* importMacOSInfo.sh */; }; DE1F1A152A8B506600A88DD8 /* exportMacOSInfo.sh in Resources */ = {isa = PBXBuildFile; fileRef = DE1F1A122A8B506600A88DD8 /* exportMacOSInfo.sh */; }; @@ -40,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 */; }; - DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A222A8B50D500A88DD8 /* BoxViewModel.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 */; }; @@ -50,6 +47,14 @@ 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 */; }; + 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 */; }; 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 */; }; @@ -77,30 +82,27 @@ DE018BEC2A509B2600FF0AA3 /* URLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLModel.swift; sourceTree = ""; }; DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarViewController.swift; sourceTree = ""; }; DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarModel.swift; sourceTree = ""; }; - DE018BF52A509B3600FF0AA3 /* MenubarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenubarView.swift; sourceTree = ""; }; DE018C022A509B5D00FF0AA3 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; DE018C192A509DBA00FF0AA3 /* Box42.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Box42.entitlements; sourceTree = ""; }; DE0A91622A8E6A5400D1D6F1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; - DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewList.swift; sourceTree = ""; }; + DE0A91662A8E6CA700D1D6F1 /* WebViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewManager.swift; sourceTree = ""; }; DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverButton.swift; sourceTree = ""; }; DE0A91772A8F014F00D1D6F1 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppleScripts+ShowMessage.swift"; sourceTree = ""; }; - DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BoxToolbarViewGroup.swift; path = Box/BoxToolbarViewGroup.swift; sourceTree = ""; }; + DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxToolbarViewGroup.swift; sourceTree = ""; }; DE0A91822A8F889000D1D6F1 /* GoHomePageViaToolbar().swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GoHomePageViaToolbar().swift"; sourceTree = ""; }; DE0A91852A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshPageViaToolbar.swift; sourceTree = ""; }; DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoForwardInToolbar.swift; sourceTree = ""; }; DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoBackInToolbar.swift; sourceTree = ""; }; DE0A918F2A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayURLInToolbar.swift; sourceTree = ""; }; DE0A91972A8F977F00D1D6F1 /* ToolbarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarViewController.swift; sourceTree = ""; }; - DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebView+CustomScroller.swift"; sourceTree = ""; }; DE0A91A62A8FC66600D1D6F1 /* SideBarLeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideBarLeading.swift; sourceTree = ""; }; 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 = ""; }; - DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxContentsViewGroup.swift; path = Box/BoxContentsViewGroup.swift; sourceTree = ""; }; - DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxButtonViewGroup.swift; path = Box/BoxButtonViewGroup.swift; sourceTree = ""; }; - DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewModel.swift; path = Main/BoxViewModel.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 = ""; }; @@ -110,6 +112,14 @@ 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 = ""; }; + 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 = ""; }; 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 = ""; }; @@ -168,6 +178,7 @@ DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, DE0A917D2A8F864300D1D6F1 /* Toolbar */, + DE4407F82A923E5B0091937A /* FunctionButton */, DE1F1A182A8B50BB00A88DD8 /* Box */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); @@ -189,9 +200,9 @@ isa = PBXGroup; children = ( DE018C0B2A509BC100FF0AA3 /* URL */, + DE0A91662A8E6CA700D1D6F1 /* WebViewManager.swift */, DE018BE92A509B2100FF0AA3 /* WebViewModel.swift */, DE018BE62A509B1E00FF0AA3 /* WebViewController.swift */, - DE0A91662A8E6CA700D1D6F1 /* WebViewList.swift */, DE0A91772A8F014F00D1D6F1 /* WebView.swift */, ); path = WebView; @@ -208,6 +219,7 @@ DE018C0C2A509BDF00FF0AA3 /* Resources */ = { isa = PBXGroup; children = ( + DEB862DE2A85348600278FCD /* sh */, DE018C192A509DBA00FF0AA3 /* Box42.entitlements */, DE018BB22A5099F900FF0AA3 /* AppDelegate.swift */, DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, @@ -223,7 +235,6 @@ children = ( DE018BEF2A509B2F00FF0AA3 /* MenubarViewController.swift */, DE018BF22A509B3300FF0AA3 /* MenubarModel.swift */, - DE018BF52A509B3600FF0AA3 /* MenubarView.swift */, DE77BA502A82580400713683 /* MenubarViewModel.swift */, ); path = Menubar; @@ -233,7 +244,6 @@ isa = PBXGroup; children = ( DE0A916C2A8E7DD700D1D6F1 /* HoverButton.swift */, - DE0A91A12A8FAC3E00D1D6F1 /* WebView+CustomScroller.swift */, DE24E6342A8FE02A00E29F5D /* MovableContainerView.swift */, ); path = UI; @@ -257,6 +267,7 @@ DE0A918C2A8F88BC00D1D6F1 /* GoBackInToolbar.swift */, DE0A91892A8F88A900D1D6F1 /* GoForwardInToolbar.swift */, DE0A91852A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift */, + DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */, ); path = View; sourceTree = ""; @@ -271,11 +282,8 @@ DE1F1A182A8B50BB00A88DD8 /* Box */ = { isa = PBXGroup; children = ( - DE0A917E2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift */, + DE4408202A9297EE0091937A /* View */, DE1F1A192A8B50C500A88DD8 /* BoxBaseContainerViewController.swift */, - DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, - DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, - DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); name = Box; sourceTree = ""; @@ -284,11 +292,44 @@ isa = PBXGroup; children = ( DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */, - DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */, + DE4408142A92750D0091937A /* keyDown+BoxViewController.swift */, ); name = Main; sourceTree = ""; }; + DE4407F82A923E5B0091937A /* FunctionButton */ = { + isa = PBXGroup; + children = ( + DE4407FC2A923E920091937A /* View */, + DE4407F92A923E860091937A /* BoxFunctionViewController.swift */, + ); + path = FunctionButton; + sourceTree = ""; + }; + DE4407FC2A923E920091937A /* View */ = { + isa = PBXGroup; + children = ( + DE44081C2A928F760091937A /* TopDivider.swift */, + DE4407FD2A923EA90091937A /* PreferenceButtonView.swift */, + DE4408012A923EB60091937A /* PinButtonView.swift */, + DE4408042A923EC00091937A /* QuitButtonView.swift */, + DE4408072A9240300091937A /* BoxFunctionButtonView.swift */, + DE44080B2A924B520091937A /* BoxFunctionViewGroup.swift */, + ); + path = View; + sourceTree = ""; + }; + DE4408202A9297EE0091937A /* View */ = { + isa = PBXGroup; + children = ( + DE1F1A1B2A8B50C500A88DD8 /* BoxButtonViewGroup.swift */, + DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, + DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, + ); + name = View; + path = Box/View; + sourceTree = ""; + }; DE77BA542A82636500713683 /* Shared */ = { isa = PBXGroup; children = ( @@ -314,7 +355,6 @@ DEB862D22A8511D600278FCD /* Scripts */ = { isa = PBXGroup; children = ( - DEB862DE2A85348600278FCD /* sh */, DEB862DB2A85347400278FCD /* Scripts.swift */, DE0A917A2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift */, ); @@ -439,19 +479,21 @@ DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, + DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, DE77BA562A82637900713683 /* StateManager.swift in Sources */, DE1F1A1C2A8B50C500A88DD8 /* BoxBaseContainerViewController.swift in Sources */, - DE018BF62A509B3600FF0AA3 /* MenubarView.swift in Sources */, DE018BE72A509B1E00FF0AA3 /* WebViewController.swift in Sources */, + DE4407FA2A923E860091937A /* BoxFunctionViewController.swift in Sources */, + DE4407FE2A923EA90091937A /* PreferenceButtonView.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, + DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */, 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 */, - DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, @@ -459,8 +501,11 @@ DE7A257A2A6D8CA20043225A /* PreferencesViewController.swift in Sources */, DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, - DE0A91672A8E6CA700D1D6F1 /* WebViewList.swift in Sources */, + DE4408022A923EB60091937A /* PinButtonView.swift in Sources */, + DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, + DE4408152A92750D0091937A /* keyDown+BoxViewController.swift in Sources */, DE018BED2A509B2600FF0AA3 /* URLModel.swift in Sources */, + DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */, DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */, DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, @@ -473,9 +518,9 @@ DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, + DE44081D2A928F760091937A /* TopDivider.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, - DE0A91A22A8FAC3F00D1D6F1 /* WebView+CustomScroller.swift in Sources */, DE0A91782A8F014F00D1D6F1 /* WebView.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE0A917F2A8F865400D1D6F1 /* BoxToolbarViewGroup.swift in Sources */, diff --git a/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme b/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme new file mode 100644 index 0000000..d8294f7 --- /dev/null +++ b/Box42.xcodeproj/xcshareddata/xcschemes/Box42.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8cf0e3be12ce94d26475753a4d5aca06c8ec38d6 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 03:59:54 +0900 Subject: [PATCH 45/55] =?UTF-8?q?feat:=20split=20view=EB=A5=BC=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=EC=84=9C=20button=EA=B3=BC=20contents?= =?UTF-8?q?=EB=A5=BC=20=EA=B5=AC=EB=B6=84=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Box/BoxBaseContainerViewController.swift | 62 +++++++++++++------ Box42/{ => Box/View}/BoxBaseSplitView.swift | 4 +- Box42/Shared/BoxSizeManager.swift | 2 + 3 files changed, 45 insertions(+), 23 deletions(-) rename Box42/{ => Box/View}/BoxBaseSplitView.swift (88%) diff --git a/Box42/Box/BoxBaseContainerViewController.swift b/Box42/Box/BoxBaseContainerViewController.swift index 6aaa7de..538078f 100644 --- a/Box42/Box/BoxBaseContainerViewController.swift +++ b/Box42/Box/BoxBaseContainerViewController.swift @@ -12,9 +12,10 @@ 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) @@ -35,17 +36,13 @@ class BoxBaseContainerViewController: NSViewController { func clickBtn(sender: NSButton) { guard let clickCount = NSApp.currentEvent?.clickCount else { return } - if sender.title == "Preferences" { - contentGroup.removeAllSubviews() - contentGroup.showPreferences() - return - } if clickCount == 2 { - WebViewList.shared.list[sender.title]!.reload() + WebViewManager.shared.list[sender.title]!.reload() print("Dobule Click") } else if clickCount > 2 { - // let rqURL = URLRequest(url: boxVM.URLdict[sender.title]!) - // WebViewList.shared.list[sender.title]!.load(rqURL) + if let currentURL = WebViewManager.shared.hostingWebView?.url { + NSWorkspace.shared.open(currentURL) + } print("Triple Click") } else if clickCount < 2 { contentGroup.removeAllSubviews() @@ -57,6 +54,29 @@ class BoxBaseContainerViewController: NSViewController { 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() { @@ -68,19 +88,9 @@ class BoxBaseContainerViewController: NSViewController { splitView.snp.makeConstraints { make in make.top.equalTo(self.view).offset(Constants.UI.GroupAutolayout) - make.bottom.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) - } - - toolbarGroup.snp.makeConstraints { make in - make.top.equalTo(leftContainer).offset(Constants.UI.GroupAutolayout) - make.left.right.equalTo(leftContainer) - } - - buttonGroup.snp.makeConstraints { make in - make.top.equalTo(toolbarGroup.snp.bottom).offset(Constants.UI.GroupAutolayout) - make.left.right.bottom.equalTo(leftContainer) + make.bottom.equalTo(self.view).offset(-Constants.UI.GroupAutolayout) } } @@ -92,6 +102,7 @@ class BoxBaseContainerViewController: NSViewController { extension BoxBaseContainerViewController: NSSplitViewDelegate { func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { + if dividerIndex == 0 { return 132 } @@ -104,4 +115,15 @@ extension BoxBaseContainerViewController: NSSplitViewDelegate { } 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/BoxBaseSplitView.swift b/Box42/Box/View/BoxBaseSplitView.swift similarity index 88% rename from Box42/BoxBaseSplitView.swift rename to Box42/Box/View/BoxBaseSplitView.swift index d432a99..3def6e3 100644 --- a/Box42/BoxBaseSplitView.swift +++ b/Box42/Box/View/BoxBaseSplitView.swift @@ -10,10 +10,8 @@ import AppKit class BoxBaseSplitView: NSSplitView { init() { super.init(frame: .zero) - self.isVertical = true - self.dividerStyle = .thin - + self.dividerStyle = .thick } required init?(coder: NSCoder) { diff --git a/Box42/Shared/BoxSizeManager.swift b/Box42/Shared/BoxSizeManager.swift index 3fe2aac..acd32f4 100644 --- a/Box42/Shared/BoxSizeManager.swift +++ b/Box42/Shared/BoxSizeManager.swift @@ -18,6 +18,7 @@ struct BoxSizeManager { var boxViewSizeNSRect: NSRect var boxViewSizeNSSize: NSSize var buttonGroupSizeNSRect: NSRect + var windowButtonGroupSize: (width: CGFloat, height: CGFloat)! init() { halfSize = (NSScreen.halfOfScreen.x, NSScreen.halfOfScreen.y) @@ -28,5 +29,6 @@ struct BoxSizeManager { 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) } } From b04de9e6158d418c4a18f10726e58f4972eb636f Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:01:21 +0900 Subject: [PATCH 46/55] =?UTF-8?q?chore(=F0=9F=9A=9A):=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EB=A5=BC=20=EB=B3=80=EA=B2=BD=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Box/BoxButtonViewGroup.swift | 181 ------------------ Box42/Box/BoxToolbarViewGroup.swift | 31 --- Box42/Box/View/BoxButtonViewGroup.swift | 92 +++++++++ .../Box/{ => View}/BoxContentsViewGroup.swift | 7 +- Box42/Main/BoxViewModel.swift | 14 -- Box42/Menubar/MenubarView.swift | 13 -- Box42/UI/GradientView.swift | 37 ---- Box42/WebView/WebViewList.swift | 23 --- 8 files changed, 95 insertions(+), 303 deletions(-) delete mode 100644 Box42/Box/BoxButtonViewGroup.swift delete mode 100644 Box42/Box/BoxToolbarViewGroup.swift create mode 100644 Box42/Box/View/BoxButtonViewGroup.swift rename Box42/Box/{ => View}/BoxContentsViewGroup.swift (90%) delete mode 100644 Box42/Main/BoxViewModel.swift delete mode 100644 Box42/Menubar/MenubarView.swift delete mode 100644 Box42/UI/GradientView.swift delete mode 100644 Box42/WebView/WebViewList.swift diff --git a/Box42/Box/BoxButtonViewGroup.swift b/Box42/Box/BoxButtonViewGroup.swift deleted file mode 100644 index 0160c5b..0000000 --- a/Box42/Box/BoxButtonViewGroup.swift +++ /dev/null @@ -1,181 +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 divider : NSBox = NSBox() - 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() - divide() - } - - 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) - } - createLoginInfo() - preferencesButton() - createQuitButton() - createPinButton() - } - - func createLoginInfo() { - - } - - @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 - } - - func createQuitButton() { - let button = NSButton() - button.title = "Quit Box" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - button.action = #selector(NSApplication.terminate(_:)) - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - self.addSubview(button) - - button.snp.makeConstraints { make in - make.leading.equalToSuperview().offset(20) - make.trailing.equalToSuperview().offset(-20) - make.bottom.equalToSuperview() - } - - lastAddedButton = button // 이 부분 추가 - } - - func createPinButton() { - let button = NSButton() - button.title = "Pin Box" - button.setButtonType(.toggle) - button.contentTintColor = .orange - button.translatesAutoresizingMaskIntoConstraints = false - - button.target = self - button.action = #selector(clickBtn(sender:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - self.addSubview(button) - - button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50).isActive = true - button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true - } - - func preferencesButton() { - let button = NSButton() - button.title = "Preferences" - button.setButtonType(.momentaryLight) - - button.translatesAutoresizingMaskIntoConstraints = false - - button.target = self - button.action = #selector(clickBtn(sender:)) - - button.isBordered = true - button.bezelStyle = .roundRect - button.showsBorderOnlyWhileMouseInside = true - - self.addSubview(button) - - button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true - button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -90).isActive = true - button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true - } - - func divide() { - divider.boxType = .separator - divider.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(divider) - NSLayoutConstraint.activate([ - divider.leadingAnchor.constraint(equalTo: self.leadingAnchor), - divider.trailingAnchor.constraint(equalTo: self.trailingAnchor), - divider.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -40), - divider.heightAnchor.constraint(equalToConstant: 1) - ]) - } - -} diff --git a/Box42/Box/BoxToolbarViewGroup.swift b/Box42/Box/BoxToolbarViewGroup.swift deleted file mode 100644 index ac17e8c..0000000 --- a/Box42/Box/BoxToolbarViewGroup.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// BoxToolbarViewGroup.swift -// Box42 -// -// Created by Chanhee Kim on 8/18/23. -// - -import AppKit -import SnapKit - -class BoxToolbarViewGroup: NSView { - var toolbarVC: ToolbarViewController? - - 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)) - - self.wantsLayer = true -// self.addSubview(toolbarVC!.view) - - toolbarVC?.view.translatesAutoresizingMaskIntoConstraints = false - toolbarVC?.view.snp.makeConstraints { make in - make.edges.equalTo(self) - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/Box42/Box/View/BoxButtonViewGroup.swift b/Box42/Box/View/BoxButtonViewGroup.swift new file mode 100644 index 0000000..44a2299 --- /dev/null +++ b/Box42/Box/View/BoxButtonViewGroup.swift @@ -0,0 +1,92 @@ +// +// 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/Box/BoxContentsViewGroup.swift b/Box42/Box/View/BoxContentsViewGroup.swift similarity index 90% rename from Box42/Box/BoxContentsViewGroup.swift rename to Box42/Box/View/BoxContentsViewGroup.swift index 0493128..215d0ce 100644 --- a/Box42/Box/BoxContentsViewGroup.swift +++ b/Box42/Box/View/BoxContentsViewGroup.swift @@ -28,7 +28,6 @@ class BoxContentsViewGroup: NSView { make.edges.equalTo(self) } } - required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") @@ -51,13 +50,13 @@ class BoxContentsViewGroup: NSView { } func showWebviews(_ sender: NSButton) { - guard let currentWebview = WebViewList.shared.list[sender.title] else { + guard let currentWebview = WebViewManager.shared.list[sender.title] else { print("No WebView found for title: \(sender.title)") return } - WebViewList.shared.hostingname = sender.title - WebViewList.shared.hostingWebView = currentWebview + WebViewManager.shared.hostingname = sender.title + WebViewManager.shared.hostingWebView = currentWebview self.addSubview(currentWebview) diff --git a/Box42/Main/BoxViewModel.swift b/Box42/Main/BoxViewModel.swift deleted file mode 100644 index 3ae31fd..0000000 --- a/Box42/Main/BoxViewModel.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// URLViewModel.swift -// Box42 -// -// Created by Chanhee Kim on 8/9/23. -// - -import Foundation -import Combine - -// CRUD 4가지 형태의 데이터 가공 create, read, update, delete -class BoxViewModel: ObservableObject { - // Box View Model은 전체적인 View Model을 담당하게 될것. -} diff --git a/Box42/Menubar/MenubarView.swift b/Box42/Menubar/MenubarView.swift deleted file mode 100644 index 7a0e63a..0000000 --- a/Box42/Menubar/MenubarView.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// MenubarView.swift -// Box42 -// -// Created by Chan on 2023/03/16. -// - -import Foundation -import AppKit - -class MenuBarView { - -} diff --git a/Box42/UI/GradientView.swift b/Box42/UI/GradientView.swift deleted file mode 100644 index 7afd87e..0000000 --- a/Box42/UI/GradientView.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// GradientView.swift -// Box42 -// -// Created by Chanhee Kim on 8/18/23. -// - -import Cocoa - -//layer caching 기법. -//레이어 캐싱: 복잡한 그래픽 연산이 필요한 뷰의 경우 wantsLayer를 true로 설정하고 shouldRasterize 속성을 true로 설정하여 렌더링 결과를 캐시할 수 있습니다. 하지만 이를 과도하게 사용하면 메모리 사용량이 증가할 수 있으므로 주의가 필요합니다. -class GradientView: NSView { - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - self.setupLayerCaching() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - self.setupLayerCaching() - } - - private func setupLayerCaching() { - self.wantsLayer = true - self.layer?.shouldRasterize = true - self.layer?.rasterizationScale = self.window?.backingScaleFactor ?? 1.0 - } - - override func draw(_ dirtyRect: NSRect) { - super.draw(dirtyRect) - - let startingColor = NSColor(red: 1.0, green: 0.804, blue: 0.0, alpha: 0.9) - let endingColor = NSColor(red: 1.0, green: 0.447, blue: 0.0, alpha: 0.7) - let gradient = NSGradient(starting: startingColor, ending: endingColor) - gradient?.draw(in: self.bounds, angle: 90) - } -} diff --git a/Box42/WebView/WebViewList.swift b/Box42/WebView/WebViewList.swift deleted file mode 100644 index b5dbe13..0000000 --- a/Box42/WebView/WebViewList.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// WebViewList.swift -// Box42 -// -// Created by Chanhee Kim on 8/17/23. -// - -import WebKit - -typealias WebViewMapping = [String : WKWebView] - -class WebViewList { - static let shared = WebViewList() - - var hostingname: String? - var hostingWebView: WKWebView? - - var list: WebViewMapping! - - private init() { - list = [:] - } -} From 68ecc98c412aa4e3c1027d0529ea9730e10c790c Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:02:15 +0900 Subject: [PATCH 47/55] =?UTF-8?q?refactor(function):=20button=EA=B7=B8?= =?UTF-8?q?=EB=A3=B9=20=ED=95=98=EB=8B=A8=EC=9D=98=20function=ED=83=AD?= =?UTF-8?q?=EC=9D=98=20=EB=B7=B0=EB=A5=BC=20=EB=B3=80=EA=B2=BD=ED=95=98?= =?UTF-8?q?=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BoxFunctionViewController.swift | 42 +++++++++++ .../View/BoxFunctionButtonView.swift | 31 ++++++++ .../View/BoxFunctionViewGroup.swift | 75 +++++++++++++++++++ Box42/FunctionButton/View/PinButtonView.swift | 31 ++++++++ .../View/PreferenceButtonView.swift | 30 ++++++++ .../FunctionButton/View/QuitButtonView.swift | 31 ++++++++ Box42/FunctionButton/View/TopDivider.swift | 28 +++++++ 7 files changed, 268 insertions(+) create mode 100644 Box42/FunctionButton/BoxFunctionViewController.swift create mode 100644 Box42/FunctionButton/View/BoxFunctionButtonView.swift create mode 100644 Box42/FunctionButton/View/BoxFunctionViewGroup.swift create mode 100644 Box42/FunctionButton/View/PinButtonView.swift create mode 100644 Box42/FunctionButton/View/PreferenceButtonView.swift create mode 100644 Box42/FunctionButton/View/QuitButtonView.swift create mode 100644 Box42/FunctionButton/View/TopDivider.swift diff --git a/Box42/FunctionButton/BoxFunctionViewController.swift b/Box42/FunctionButton/BoxFunctionViewController.swift new file mode 100644 index 0000000..a2a482e --- /dev/null +++ b/Box42/FunctionButton/BoxFunctionViewController.swift @@ -0,0 +1,42 @@ +// +// FunctionButtonViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +import Cocoa + +class BoxFunctionViewController: NSViewController { + override func loadView() { + let functionViewGroup = BoxFunctionViewGroup() + + functionViewGroup.preferenceAction = preference + functionViewGroup.pinAction = pin + functionViewGroup.quitAction = quit + functionViewGroup.boxAction = box + + self.view = functionViewGroup + } + + override func viewDidLoad() { + super.viewDidLoad() + } + + func preference() { + print("preference") + } + + func pin() { + print("pin") + } + + func quit() { + print("quit") + NSApplication.shared.terminate(self) + } + + func box() { + print("box") + } +} diff --git a/Box42/FunctionButton/View/BoxFunctionButtonView.swift b/Box42/FunctionButton/View/BoxFunctionButtonView.swift new file mode 100644 index 0000000..01eb568 --- /dev/null +++ b/Box42/FunctionButton/View/BoxFunctionButtonView.swift @@ -0,0 +1,31 @@ +// +// BoxFunctionButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +import AppKit + +class BoxFunctionButtonView: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(BoxFunction) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func BoxFunction() { + callback?() + } +} diff --git a/Box42/FunctionButton/View/BoxFunctionViewGroup.swift b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift new file mode 100644 index 0000000..9e5fa88 --- /dev/null +++ b/Box42/FunctionButton/View/BoxFunctionViewGroup.swift @@ -0,0 +1,75 @@ +// +// BoxFunctionViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +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?() }) + + var preferenceAction: (() -> Void)? + var pinAction: (() -> Void)? + var quitAction: (() -> Void)? + var boxAction: (() -> Void)? + var dividerAction: (() -> 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(preferenceButton) + self.addSubview(pinButton) + self.addSubview(quitButton) + self.addSubview(boxButton) + self.addSubview(divider) + } + + private func setupConstraints() { + divider.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.right.equalToSuperview() + } + + 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) + } + + 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() + } + } +} diff --git a/Box42/FunctionButton/View/PinButtonView.swift b/Box42/FunctionButton/View/PinButtonView.swift new file mode 100644 index 0000000..a91036b --- /dev/null +++ b/Box42/FunctionButton/View/PinButtonView.swift @@ -0,0 +1,31 @@ +// +// PinButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +import AppKit + +class PinButtonView: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(pin) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func pin() { + callback?() + } +} diff --git a/Box42/FunctionButton/View/PreferenceButtonView.swift b/Box42/FunctionButton/View/PreferenceButtonView.swift new file mode 100644 index 0000000..ffc8102 --- /dev/null +++ b/Box42/FunctionButton/View/PreferenceButtonView.swift @@ -0,0 +1,30 @@ +// +// PreferenceButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +import AppKit + +class PreferenceButtonView: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(preference) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func preference() { + callback?() + } +} diff --git a/Box42/FunctionButton/View/QuitButtonView.swift b/Box42/FunctionButton/View/QuitButtonView.swift new file mode 100644 index 0000000..aaf9259 --- /dev/null +++ b/Box42/FunctionButton/View/QuitButtonView.swift @@ -0,0 +1,31 @@ +// +// QuitButtonView.swift +// Box42 +// +// Created by Chanhee Kim on 8/20/23. +// + +import AppKit + +class QuitButtonView: NSButton { + + private var callback: (() -> Void)? + + init(image: NSImage, completion: @escaping () -> Void) { + super.init(frame: .zero) + + self.image = image + self.bezelStyle = .texturedRounded + self.target = self + self.action = #selector(QuitButton) + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func QuitButton() { + callback?() + } +} diff --git a/Box42/FunctionButton/View/TopDivider.swift b/Box42/FunctionButton/View/TopDivider.swift new file mode 100644 index 0000000..81a39de --- /dev/null +++ b/Box42/FunctionButton/View/TopDivider.swift @@ -0,0 +1,28 @@ +// +// TopDivider.swift +// Box42 +// +// Created by Chanhee Kim on 8/21/23. +// + +import AppKit + +class TopDivider: NSBox { + + private var callback: (() -> Void)? + + init(completion: @escaping () -> Void) { + super.init(frame: .zero) + self.title = "" + self.boxType = .separator + self.callback = completion + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func preference() { + callback?() + } +} From 3561a72032ac9077f8db25a10a9afb5013add8f1 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:02:41 +0900 Subject: [PATCH 48/55] =?UTF-8?q?refactor:=20=EC=95=8C=EC=95=84=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EC=89=BD=EA=B2=8C=20keydown=EC=9D=84=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Main/BoxViewController.swift | 28 +----------------- Box42/Main/keyDown+BoxViewController.swift | 33 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 Box42/Main/keyDown+BoxViewController.swift diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index 15e782b..a9692c8 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -5,7 +5,6 @@ // Created by Chan on 2023/03/16. // -import Cocoa import AppKit import WebKit @@ -49,7 +48,7 @@ class BoxViewController: NSViewController { @objc func doubleClickBtn(sender: NSButton) { - WebViewList.shared.list[sender.title]!.reload() + WebViewManager.shared.list[sender.title]!.reload() } @objc @@ -62,28 +61,3 @@ class BoxViewController: NSViewController { print(message.name) } } - -extension BoxViewController { - override func keyDown(with event: NSEvent) { - print(event.keyCode) - if event.keyCode == 1 { - StorageConfig.shared.setThreshold(.percentage50) - StorageConfig.shared.setPeriod(.period10s) - } - if event.keyCode == 2 { - // SdtorageConfig.shared.setThreshold(.percentage30) - DispatchQueue.main.async { - StorageConfig.shared.setThreshold(.percentage30) - } - StorageConfig.shared.setPeriod(.period1s) - } - - - if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. - print("escape") - menubarVCDelegate?.toggleWindow(sender: nil) - } else { - super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 - } - } -} diff --git a/Box42/Main/keyDown+BoxViewController.swift b/Box42/Main/keyDown+BoxViewController.swift new file mode 100644 index 0000000..63b89e2 --- /dev/null +++ b/Box42/Main/keyDown+BoxViewController.swift @@ -0,0 +1,33 @@ +// +// keyDown+BoxViewController.swift +// Box42 +// +// Created by Chanhee Kim on 8/21/23. +// + +import AppKit + +extension BoxViewController { + override func keyDown(with event: NSEvent) { + print(event.keyCode) + if event.keyCode == 1 { + StorageConfig.shared.setThreshold(.percentage50) + StorageConfig.shared.setPeriod(.period10s) + } + if event.keyCode == 2 { + // SdtorageConfig.shared.setThreshold(.percentage30) + DispatchQueue.main.async { + StorageConfig.shared.setThreshold(.percentage30) + } + StorageConfig.shared.setPeriod(.period1s) + } + + + if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. + print("escape") + menubarVCDelegate?.toggleWindow(sender: nil) + } else { + super.keyDown(with: event) // 기타 키를 처리하기 위해 상위 클래스에게 전달 + } + } +} From ac3b11d81ab8b154b7919de3ca171cc8dfad78a7 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:03:37 +0900 Subject: [PATCH 49/55] =?UTF-8?q?chore:=20=EC=93=B8=EB=AA=A8=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EB=B6=80=EB=B6=84=EC=9D=84=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Menubar/MenubarViewController.swift | 1 - .../PreferencesViewController.swift | 30 ++++++++--------- Box42/System/Storage.swift | 33 +++++++++---------- Box42/System/StorageConfig.swift | 2 +- Box42/WebView/WebViewController.swift | 25 +++++--------- 5 files changed, 40 insertions(+), 51 deletions(-) diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index a409ed8..2cb1a3f 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -11,7 +11,6 @@ import AppKit class MenubarViewController: NSWorkspace { var popover = NSPopover() var statusBarVM = StatusBarViewModel() - let menuBarView = MenuBarView() lazy var eventMonitor: EventMonitor = self.setupEventMonitor() var boxWindowController: BoxWindowController? diff --git a/Box42/Preferences/PreferencesViewController.swift b/Box42/Preferences/PreferencesViewController.swift index 786e21d..6604203 100644 --- a/Box42/Preferences/PreferencesViewController.swift +++ b/Box42/Preferences/PreferencesViewController.swift @@ -104,21 +104,21 @@ class PreferencesViewController: NSViewController { task.standardError = outputPipe - outputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in - if #available(OSX 10.15.4, *) { - if let data = try? fileHandle.readToEnd(), let output = String(data: data, encoding: .utf8) { - DispatchQueue.main.async { - if let outputView = self?.outputView { - outputView.string += "\(output)" - } else { - print("outputView is nil") - } - } - } - } else { - // Fallback on earlier versions - } - } +// outputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in +// if #available(OSX 10.15.4, *) { +// if let data = try? fileHandle.readToEnd(), let output = String(data: data, encoding: .utf8) { +// DispatchQueue.main.async { +// if let outputView = self?.outputView { +// outputView.string += "\(output)" +// } else { +// print("outputView is nil") +// } +// } +// } +// } else { +// // Fallback on earlier versions +// } +// } task.launch() diff --git a/Box42/System/Storage.swift b/Box42/System/Storage.swift index 6b06a22..4024446 100644 --- a/Box42/System/Storage.swift +++ b/Box42/System/Storage.swift @@ -73,23 +73,22 @@ class Storage { self.cleanSh() self.count += 1 if self.count > 2 { - showMessageWithAppleScript("캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요.", "재시작") { button in - print("timer") - dump(button) - if let button = button { - switch button { - case "재시작": - StateManager.shared.setOnIsAutoStorage() - print("재시작 버튼을 클릭했습니다.") - case "취소": - // 취소 관련 로직 실행 - print("취소 버튼을 클릭했습니다.") - default: - break - } - } - } - +// showMessageWithAppleScript("캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요.", "재시작") { button in +// print("timer") +// dump(button) +// if let button = button { +// switch button { +// case "재시작": +// StateManager.shared.setOnIsAutoStorage() +// print("재시작 버튼을 클릭했습니다.") +// case "취소": +// // 취소 관련 로직 실행 +// print("취소 버튼을 클릭했습니다.") +// default: +// break +// } +// } +// } StateManager.shared.setOffIsAutoStorage() // 여기서도 타이머를 중지시켜야 합니다. self.storageTimer?.invalidate() diff --git a/Box42/System/StorageConfig.swift b/Box42/System/StorageConfig.swift index 7b9f615..002581c 100644 --- a/Box42/System/StorageConfig.swift +++ b/Box42/System/StorageConfig.swift @@ -27,7 +27,7 @@ class StorageConfig: ObservableObject { @Published var threshold: StorageThreshold @Published var period: StoragePeriod - init(_ threshold: StorageThreshold = .percentage10, _ period: StoragePeriod = .period3s) { + init(_ threshold: StorageThreshold = .percentage30, _ period: StoragePeriod = .period3s) { self.threshold = threshold self.period = period } diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 3b73e89..e0d1f02 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -31,7 +31,7 @@ class WebViewController: NSViewController { func loadWebView(_ name: String, _ url: URL) { let wkWebView = WebView() - WebViewList.shared.list[name] = wkWebView + WebViewManager.shared.list[name] = wkWebView DispatchQueue.main.async { wkWebView.load(self.URLVM.requestURL(url)) } @@ -44,7 +44,7 @@ class WebViewController: NSViewController { } func webViewInit() { - WebViewList.shared.hostingWebView = self.webView + WebViewManager.shared.hostingWebView = self.webView DispatchQueue.main.async { self.webView.load(self.URLVM.requestURL(self.URLVM.safeURL())) } @@ -60,25 +60,16 @@ class WebViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - if let scrollView = webView.enclosingScrollView { - scrollView.verticalScroller = CustomScroller() - scrollView.horizontalScroller = CustomScroller() - } } func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { print(message.name) } -} - -extension WebViewController { - override func keyDown(with event: NSEvent) { - print(event.keyCode) - - // 키보드 이벤트 처리 - // if (event) { - // } else { - // super.keyDown(with: event) // 기본 키 이벤트 처리 - // } + + func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { + if let url = navigationAction.request.url { + webView.load(URLRequest(url: url)) + } + return nil } } From ec556f1277bc1330b4dae1d41ed4813e52188fc6 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:05:00 +0900 Subject: [PATCH 50/55] =?UTF-8?q?refactor(webview):=20=EC=8B=B1=EA=B8=80?= =?UTF-8?q?=ED=86=A4=20=ED=8C=A8=ED=84=B4=20=EA=B5=AC=EC=A1=B0=EC=9D=98=20?= =?UTF-8?q?WebViewManager=EB=A1=9C=20content=20hosting=20view=EB=A5=BC=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=98=EA=B2=8C=20=EB=90=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/Toolbar/ToolbarViewController.swift | 10 +++--- Box42/Toolbar/View/BoxToolbarViewGroup.swift | 31 +++++++++++++++++ Box42/Toolbar/View/DisplayURLInToolbar.swift | 4 +-- Box42/WebView/WebViewManager.swift | 23 +++++++++++++ Box42/Window/BoxWindowController.swift | 35 +++++++++++++------- 5 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 Box42/Toolbar/View/BoxToolbarViewGroup.swift create mode 100644 Box42/WebView/WebViewManager.swift diff --git a/Box42/Toolbar/ToolbarViewController.swift b/Box42/Toolbar/ToolbarViewController.swift index c31b378..ea32aab 100644 --- a/Box42/Toolbar/ToolbarViewController.swift +++ b/Box42/Toolbar/ToolbarViewController.swift @@ -38,20 +38,20 @@ class ToolbarViewController: NSViewController { } func goBack() { - WebViewList.shared.hostingWebView?.goBack() + WebViewManager.shared.hostingWebView?.goBack() } func goFoward() { - WebViewList.shared.hostingWebView?.goForward() + WebViewManager.shared.hostingWebView?.goForward() } func reloadPage() { - WebViewList.shared.hostingWebView?.reload() + WebViewManager.shared.hostingWebView?.reload() } func goToHome() { - if let item = WebViewList.shared.hostingWebView?.backForwardList.backList.first { - WebViewList.shared.hostingWebView?.go(to: item) + if let item = WebViewManager.shared.hostingWebView?.backForwardList.backList.first { + WebViewManager.shared.hostingWebView?.go(to: item) } } } diff --git a/Box42/Toolbar/View/BoxToolbarViewGroup.swift b/Box42/Toolbar/View/BoxToolbarViewGroup.swift new file mode 100644 index 0000000..ac17e8c --- /dev/null +++ b/Box42/Toolbar/View/BoxToolbarViewGroup.swift @@ -0,0 +1,31 @@ +// +// BoxToolbarViewGroup.swift +// Box42 +// +// Created by Chanhee Kim on 8/18/23. +// + +import AppKit +import SnapKit + +class BoxToolbarViewGroup: NSView { + var toolbarVC: ToolbarViewController? + + 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)) + + self.wantsLayer = true +// self.addSubview(toolbarVC!.view) + + toolbarVC?.view.translatesAutoresizingMaskIntoConstraints = false + toolbarVC?.view.snp.makeConstraints { make in + make.edges.equalTo(self) + } + } + + 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 147c39f..d8026dd 100644 --- a/Box42/Toolbar/View/DisplayURLInToolbar.swift +++ b/Box42/Toolbar/View/DisplayURLInToolbar.swift @@ -16,7 +16,7 @@ class DisplayURLInToolbar: NSTextField { self.isBordered = false // 테두리를 제거합니다. self.backgroundColor = NSColor.clear // 배경색을 투명하게 만듭니다. - if let url = WebViewList.shared.hostingWebView?.url { + if let url = WebViewManager.shared.hostingWebView?.url { self.stringValue = url.absoluteString } } @@ -26,7 +26,7 @@ class DisplayURLInToolbar: NSTextField { } func updateURL() { - if let url = WebViewList.shared.hostingWebView?.url { + if let url = WebViewManager.shared.hostingWebView?.url { self.stringValue = url.absoluteString } } diff --git a/Box42/WebView/WebViewManager.swift b/Box42/WebView/WebViewManager.swift new file mode 100644 index 0000000..bdf0fe1 --- /dev/null +++ b/Box42/WebView/WebViewManager.swift @@ -0,0 +1,23 @@ +// +// WebViewList.swift +// Box42 +// +// Created by Chanhee Kim on 8/17/23. +// + +import WebKit + +typealias WebViewMapping = [String : WKWebView] + +class WebViewManager { + static let shared = WebViewManager() + + var hostingname: String? + var hostingWebView: WKWebView? + + var list: WebViewMapping! + + private init() { + list = [:] + } +} diff --git a/Box42/Window/BoxWindowController.swift b/Box42/Window/BoxWindowController.swift index 8ce6c4c..dc69045 100644 --- a/Box42/Window/BoxWindowController.swift +++ b/Box42/Window/BoxWindowController.swift @@ -7,14 +7,14 @@ import Cocoa -class BoxWindowController: NSWindowController, NSToolbarDelegate { +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" @@ -22,21 +22,32 @@ class BoxWindowController: NSWindowController, NSToolbarDelegate { 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") } - - // MARK: - Toolbar - +} + +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 @@ -99,20 +110,20 @@ class BoxWindowController: NSWindowController, NSToolbarDelegate { } @objc func goBackAction() { - WebViewList.shared.hostingWebView?.goBack() + WebViewManager.shared.hostingWebView?.goBack() } @objc func goFowardAction() { - WebViewList.shared.hostingWebView?.goForward() + WebViewManager.shared.hostingWebView?.goForward() } @objc func reloadPageAction() { - WebViewList.shared.hostingWebView?.reload() + WebViewManager.shared.hostingWebView?.reload() } @objc func goToHomeAction() { - if let item = WebViewList.shared.hostingWebView?.backForwardList.backList.first { - WebViewList.shared.hostingWebView?.go(to: item) + if let item = WebViewManager.shared.hostingWebView?.backForwardList.backList.first { + WebViewManager.shared.hostingWebView?.go(to: item) } } } From b8f6fef7b5c28e6e596f1cdedef471c9c54f00b2 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Mon, 21 Aug 2023 04:06:31 +0900 Subject: [PATCH 51/55] =?UTF-8?q?feat(front):=20=E2=9C=A8=20front=20deploy?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=9D=BC=EC=84=9C=20url=EC=9D=84=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=ED=95=A9=EB=8B=88=EB=8B=A4!=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Box42/WebView/URL/URLModel.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Box42/WebView/URL/URLModel.swift b/Box42/WebView/URL/URLModel.swift index d27e9e3..014f62c 100644 --- a/Box42/WebView/URL/URLModel.swift +++ b/Box42/WebView/URL/URLModel.swift @@ -26,7 +26,8 @@ struct URLModels { // Network logic api call 날려서 받아올 것. let URLstring: [nameUrl] = [ - ("home", "https://42box.github.io/front-end/"), + ("home", "http://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"), From 895fa32b3db22c2f150b3541b8936d24884deb30 Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Tue, 22 Aug 2023 16:44:09 +0900 Subject: [PATCH 52/55] ci: xcode swift build / archive / deploy (#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: 🛠 * ci: 📃 * ci(🛠): ci/cd 부분을 분리합니다 ! --- .github/workflows/Deployment.yml | 60 +++++++++++++++++++++++++++++ .github/workflows/swift.yml | 23 ++++++----- Box42/Resources/ExportOptions.plist | 14 +++++++ 3 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/Deployment.yml create mode 100644 Box42/Resources/ExportOptions.plist diff --git a/.github/workflows/Deployment.yml b/.github/workflows/Deployment.yml new file mode 100644 index 0000000..87ea009 --- /dev/null +++ b/.github/workflows/Deployment.yml @@ -0,0 +1,60 @@ +# Author by chanhihi +# Date 2023.08.09 + +name: Deployment + +on: + push: + branches: + - cluster_main + - main + tags: + - "v*" + +jobs: + build: + name: Deploy on macOS 11 + runs-on: macos-11 + env: + XCODE_VERSION: "12.4.0" + SWIFT_VERSION: "5.3" + XCODE_PROJECT: "Box42.xcodeproj" + XCODE_SCHEME: "Box42" + XCODE_ARCHIVE_PATH: "Box42.xcarchive" + XCODE_EXPORT_PATH: "./artifacts" + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set Xcode version + run: sudo xcode-select -s '/Applications/Xcode_12.4.0.app/Contents/Developer' + + - name: Set SDK version + run: echo 'SDKROOT=/Applications/Xcode_12.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk' >> $GITHUB_ENV + + - name: setup-swift + uses: swift-actions/setup-swift@v1 + with: + swift-version: $SWIFT_VERSION + + - name: Build + run: | + mkdir Sources && + mv Box42 Sources/Box42 && + swift build + + - name: Archive + run: | + mv Sources/Box42/Resources/ExportOptions.plist . && + xcodebuild archive -project $XCODE_PROJECT -scheme $XCODE_SCHEME -archivePath $XCODE_ARCHIVE_PATH + + - name: Distribute + run: | + mkdir -p artifacts && + xcodebuild -exportArchive -archivePath "$XCODE_ARCHIVE_PATH" -exportOptionsPlist ExportOptions.plist -exportPath "$XCODE_EXPORT_PATH" + + - name: Upload Box42-Artifacts + uses: actions/upload-artifact@v2 + with: + name: Box42-${{ github.ref_name }} + path: $XCODE_EXPORT_PATH diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 668423e..976d883 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -5,36 +5,39 @@ name: Swift Build on: push: - branches: [ "feat/*", "fix/*", "refactor/*", "cluster_main", "main" ] + branches: + - feat/* + - fix/* + - refactor/* + pull_request: - branches: [ "cluster_develop" ] + branches: + - cluster_develop jobs: build: name: Swift 5.3 on macOS 11 runs-on: macos-11 + env: + XCODE_VERSION: "12.4.0" + SWIFT_VERSION: "5.3" steps: - name: Checkout uses: actions/checkout@v3 - name: Set Xcode version - run: - sudo xcode-select -s '/Applications/Xcode_12.4.0.app/Contents/Developer' + run: sudo xcode-select -s '/Applications/Xcode_12.4.0.app/Contents/Developer' - name: Set SDK version - run: - echo 'SDKROOT=/Applications/Xcode_12.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk' >> $GITHUB_ENV + run: echo 'SDKROOT=/Applications/Xcode_12.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk' >> $GITHUB_ENV - name: setup-swift uses: swift-actions/setup-swift@v1 with: - swift-version: 5.3 + swift-version: ${{ env.SWIFT_VERSION }} - name: Build run: | mkdir Sources && mv Box42 Sources/Box42 && swift build - -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift diff --git a/Box42/Resources/ExportOptions.plist b/Box42/Resources/ExportOptions.plist new file mode 100644 index 0000000..31694a6 --- /dev/null +++ b/Box42/Resources/ExportOptions.plist @@ -0,0 +1,14 @@ + + + + + destination + export + method + development + signingStyle + automatic + teamID + QUAC995NAA + + From 684a82cbe87a98db4cd3934df72bcf16a9f6890c Mon Sep 17 00:00:00 2001 From: KIM CHAN HEE <85754295+chanhihi@users.noreply.github.com> Date: Tue, 22 Aug 2023 18:43:57 +0900 Subject: [PATCH 53/55] test: cicd test (#52) --- .github/release-drafter-config.yml | 23 ++++++++++++++++++++ .github/workflows/Deployment.yml | 6 ++--- .github/workflows/Release.yml | 35 ++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 .github/release-drafter-config.yml create mode 100644 .github/workflows/Release.yml diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml new file mode 100644 index 0000000..e2d8534 --- /dev/null +++ b/.github/release-drafter-config.yml @@ -0,0 +1,23 @@ +name-template: "v$NEXT_MINOR_VERSION 🌈" +tag-template: "v$NEXT_MINOR_VERSION" +categories: + - title: "🚀 Features" + labels: + - "✨ Enhancement" + - "⚒ Refactor" + - title: "🐛 Bug Fixes" + labels: + - "🐞 Bug" +exclude-labels: + - "📄 Documentation" + - "🌐 DevOps" + - "💄 UI/UX" + - "🏛 Structure" + - "💖 Question" + - "☂️ Umbrella" +change-template: "- $TITLE (#$NUMBER)" +change-title-escapes: '\<*_&' +template: | + ## Changes + + $CHANGES diff --git a/.github/workflows/Deployment.yml b/.github/workflows/Deployment.yml index 87ea009..0c92aba 100644 --- a/.github/workflows/Deployment.yml +++ b/.github/workflows/Deployment.yml @@ -6,10 +6,8 @@ name: Deployment on: push: branches: - - cluster_main - - main - tags: - - "v*" + - main-ci-cd-test + # - main jobs: build: diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml new file mode 100644 index 0000000..4eb9421 --- /dev/null +++ b/.github/workflows/Release.yml @@ -0,0 +1,35 @@ +# Author by chanhihi +# Date 2023.08.22 + +name: Release Drafter + +on: + pull_request: + branches: + - main-ci-cd-test + types: + - closed + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - name: Tag + if: success() + id: tag_version + uses: mathieudutour/github-tag-action@v6.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create a GitHub release + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.tag_version.outputs.new_tag }} + name: Release ${{ steps.tag_version.outputs.new_tag }} + body: ${{ steps.tag_version.outputs.changelog }} + + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter-config.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From ac5169df47eda7e4ca698bc735589ba898efa358 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Tue, 22 Aug 2023 18:57:33 +0900 Subject: [PATCH 54/55] test: release test --- .github/workflows/Deployment.yml | 2 +- .github/workflows/Release.yml | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Deployment.yml b/.github/workflows/Deployment.yml index 0c92aba..85bdb99 100644 --- a/.github/workflows/Deployment.yml +++ b/.github/workflows/Deployment.yml @@ -6,7 +6,7 @@ name: Deployment on: push: branches: - - main-ci-cd-test + - main-cicd-test # - main jobs: diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 4eb9421..db54b4d 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -6,7 +6,7 @@ name: Release Drafter on: pull_request: branches: - - main-ci-cd-test + - main-cicd-test types: - closed @@ -14,12 +14,11 @@ jobs: update_release_draft: runs-on: ubuntu-latest steps: - - name: Tag - if: success() + - name: Tagging id: tag_version uses: mathieudutour/github-tag-action@v6.1 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.CHANHIHI }} - name: Create a GitHub release uses: ncipollo/release-action@v1 @@ -32,4 +31,4 @@ jobs: with: config-name: release-drafter-config.yml env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.CHANHIHI }} From 51775ab2079f5ae44fa77ae0bbaccde8e23cbef7 Mon Sep 17 00:00:00 2001 From: chanhihi Date: Tue, 22 Aug 2023 19:15:42 +0900 Subject: [PATCH 55/55] =?UTF-8?q?test:=20release=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=B4=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...se-drafter-config.yml => Release-note.yml} | 0 .github/workflows/Deployment.yml | 3 +-- .github/workflows/Release.yml | 21 +++++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) rename .github/{release-drafter-config.yml => Release-note.yml} (100%) diff --git a/.github/release-drafter-config.yml b/.github/Release-note.yml similarity index 100% rename from .github/release-drafter-config.yml rename to .github/Release-note.yml diff --git a/.github/workflows/Deployment.yml b/.github/workflows/Deployment.yml index 85bdb99..c4dceba 100644 --- a/.github/workflows/Deployment.yml +++ b/.github/workflows/Deployment.yml @@ -6,8 +6,7 @@ name: Deployment on: push: branches: - - main-cicd-test - # - main + - release-test jobs: build: diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index db54b4d..82b6a33 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -1,17 +1,17 @@ # Author by chanhihi # Date 2023.08.22 -name: Release Drafter +name: Release Drafter and Tagging on: pull_request: branches: - - main-cicd-test + - release-test types: - closed jobs: - update_release_draft: + release_process: runs-on: ubuntu-latest steps: - name: Tagging @@ -20,15 +20,18 @@ jobs: with: github_token: ${{ secrets.CHANHIHI }} + - name: Draft Release + id: draft_release + uses: release-drafter/release-drafter@v5 + with: + config-name: Release-note.yml + env: + GITHUB_TOKEN: ${{ secrets.CHANHIHI }} + - name: Create a GitHub release uses: ncipollo/release-action@v1 with: + token: ${{ secrets.CHANHIHI }} tag: ${{ steps.tag_version.outputs.new_tag }} name: Release ${{ steps.tag_version.outputs.new_tag }} body: ${{ steps.tag_version.outputs.changelog }} - - - uses: release-drafter/release-drafter@v5 - with: - config-name: release-drafter-config.yml - env: - GITHUB_TOKEN: ${{ secrets.CHANHIHI }}