diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index f2eb8dd..229e011 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -98,6 +98,13 @@ DE9457342A9FB1D300B0B768 /* RequestAccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457332A9FB1D300B0B768 /* RequestAccessView.swift */; }; DE9457372A9FC0A800B0B768 /* SecurityScopedResourceAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457362A9FC0A800B0B768 /* SecurityScopedResourceAccess.swift */; }; DE94573D2A9FD33400B0B768 /* StorageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94573C2A9FD33400B0B768 /* StorageView.swift */; }; + DE9457442AA0A1B300B0B768 /* MemoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457432AA0A1B300B0B768 /* MemoryView.swift */; }; + DE9457482AA0A34500B0B768 /* BatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457472AA0A34500B0B768 /* BatteryView.swift */; }; + DE94574B2AA0A70500B0B768 /* NetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94574A2AA0A70500B0B768 /* NetworkView.swift */; }; + DE94574E2AA0B56200B0B768 /* CPUView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94574D2AA0B56200B0B768 /* CPUView.swift */; }; + DE9457512AA0BE0F00B0B768 /* NotificationSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457502AA0BE0F00B0B768 /* NotificationSettingView.swift */; }; + DE9457542AA0BF5200B0B768 /* ShortcutSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457532AA0BF5200B0B768 /* ShortcutSettingView.swift */; }; + DE9457572AA0C5C600B0B768 /* IconSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457562AA0C5C600B0B768 /* IconSettingView.swift */; }; DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */; }; DE97CA792A9A6F6A001073DE /* QuickSlotHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */; }; DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */; }; @@ -112,6 +119,7 @@ DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862E92A853F7F00278FCD /* BoxWindowController.swift */; }; DEE0FA962A9A554F00085A65 /* FunctionButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */; }; + DEF0761B2AA33671005700E5 /* DeleteUserMeScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF0761A2AA33671005700E5 /* DeleteUserMeScript.swift */; }; DEF749322A85657600D987C8 /* NSScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF749312A85657600D987C8 /* NSScreen.swift */; }; /* End PBXBuildFile section */ @@ -209,6 +217,13 @@ DE9457332A9FB1D300B0B768 /* RequestAccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestAccessView.swift; sourceTree = ""; }; DE9457362A9FC0A800B0B768 /* SecurityScopedResourceAccess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityScopedResourceAccess.swift; sourceTree = ""; }; DE94573C2A9FD33400B0B768 /* StorageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageView.swift; sourceTree = ""; }; + DE9457432AA0A1B300B0B768 /* MemoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryView.swift; sourceTree = ""; }; + DE9457472AA0A34500B0B768 /* BatteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryView.swift; sourceTree = ""; }; + DE94574A2AA0A70500B0B768 /* NetworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkView.swift; sourceTree = ""; }; + DE94574D2AA0B56200B0B768 /* CPUView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUView.swift; sourceTree = ""; }; + DE9457502AA0BE0F00B0B768 /* NotificationSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingView.swift; sourceTree = ""; }; + DE9457532AA0BF5200B0B768 /* ShortcutSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutSettingView.swift; sourceTree = ""; }; + DE9457562AA0C5C600B0B768 /* IconSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSettingView.swift; sourceTree = ""; }; DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PixelConversion+CGFloat.swift"; sourceTree = ""; }; DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewModel.swift; sourceTree = ""; }; DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonModel.swift; sourceTree = ""; }; @@ -223,6 +238,7 @@ DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862E92A853F7F00278FCD /* BoxWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxWindowController.swift; sourceTree = ""; }; DEE0FA952A9A554F00085A65 /* FunctionButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionButtonUI.swift; sourceTree = ""; }; + DEF0761A2AA33671005700E5 /* DeleteUserMeScript.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteUserMeScript.swift; sourceTree = ""; }; DEF7492E2A85603700D987C8 /* nodeInstall.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = nodeInstall.sh; sourceTree = ""; }; DEF749312A85657600D987C8 /* NSScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSScreen.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -447,6 +463,7 @@ DE77BBA92A9DE680006CC98B /* GetUserProfile.swift */, DE9457272A9F6E4400B0B768 /* GetUserMeScripts.swift */, DE94572B2A9F75D500B0B768 /* API.swift */, + DEF0761A2AA33671005700E5 /* DeleteUserMeScript.swift */, ); path = API; sourceTree = ""; @@ -595,6 +612,13 @@ children = ( DE9457332A9FB1D300B0B768 /* RequestAccessView.swift */, DE94573C2A9FD33400B0B768 /* StorageView.swift */, + DE9457432AA0A1B300B0B768 /* MemoryView.swift */, + DE9457472AA0A34500B0B768 /* BatteryView.swift */, + DE94574A2AA0A70500B0B768 /* NetworkView.swift */, + DE94574D2AA0B56200B0B768 /* CPUView.swift */, + DE9457502AA0BE0F00B0B768 /* NotificationSettingView.swift */, + DE9457532AA0BF5200B0B768 /* ShortcutSettingView.swift */, + DE9457562AA0C5C600B0B768 /* IconSettingView.swift */, ); path = Funtion; sourceTree = ""; @@ -816,6 +840,7 @@ DE0A91A72A8FC66600D1D6F1 /* SideBarLeading.swift in Sources */, DE0A917B2A8F0CA800D1D6F1 /* AppleScripts+ShowMessage.swift in Sources */, DE018BB82A5099F900FF0AA3 /* Box42.xcdatamodeld in Sources */, + DEF0761B2AA33671005700E5 /* DeleteUserMeScript.swift in Sources */, DE62BE672A9BA92E00D97E06 /* QuickSlotButtonViewItem.swift in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */, @@ -826,6 +851,7 @@ DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */, DE9457192A9EEEF000B0B768 /* ScriptCellManager.swift in Sources */, DE9457002A9E5B0900B0B768 /* ScriptCell.swift in Sources */, + DE9457442AA0A1B300B0B768 /* MemoryView.swift in Sources */, DE7886042A9C71CB00FE21DD /* ScriptsTableView.swift in Sources */, DE9457312A9FB01400B0B768 /* PreferencesTableView.swift in Sources */, DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */, @@ -854,6 +880,7 @@ DE77BBA62A9DDF2B006CC98B /* WebView.swift in Sources */, DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */, DE6332F22A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift in Sources */, + DE9457512AA0BE0F00B0B768 /* NotificationSettingView.swift in Sources */, DE9457342A9FB1D300B0B768 /* RequestAccessView.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE78860C2A9C770300FE21DD /* ScriptsViewModel.swift in Sources */, @@ -867,6 +894,7 @@ DE24E63B2A8FE93900E29F5D /* NSImage.swift in Sources */, DE94570F2A9E69F200B0B768 /* ScriptDeleteButton.swift in Sources */, DE97CA792A9A6F6A001073DE /* QuickSlotHeaderView.swift in Sources */, + DE9457482AA0A34500B0B768 /* BatteryView.swift in Sources */, DE9457372A9FC0A800B0B768 /* SecurityScopedResourceAccess.swift in Sources */, DE0A916D2A8E7DD700D1D6F1 /* HoverButton.swift in Sources */, DE97CA862A9A7404001073DE /* QuickSlotViewModel.swift in Sources */, @@ -876,9 +904,11 @@ DE9457282A9F6E4400B0B768 /* GetUserMeScripts.swift in Sources */, DE77BBD22A9E0AE8006CC98B /* WebViewUI.swift in Sources */, DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */, + DE9457542AA0BF5200B0B768 /* ShortcutSettingView.swift in Sources */, DE4408022A923EB60091937A /* PinButtonView.swift in Sources */, DE77BBE22A9E0F70006CC98B /* Scripts.swift in Sources */, DE78862D2A9D1ADE00FE21DD /* PreferencesCell.swift in Sources */, + DE9457572AA0C5C600B0B768 /* IconSettingView.swift in Sources */, DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, DE77BBF32A9E38DC006CC98B /* UserManager.swift in Sources */, DE94570C2A9E69EB00B0B768 /* ScriptExcuteButton.swift in Sources */, @@ -893,6 +923,7 @@ DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, DE0A918D2A8F88BC00D1D6F1 /* GoBackInToolbar.swift in Sources */, + DE94574E2AA0B56200B0B768 /* CPUView.swift in Sources */, DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, DE3FF3672A978A37009C88EF /* HexValue+NSColor.swift in Sources */, DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, @@ -903,6 +934,7 @@ DE24E6382A8FE10400E29F5D /* BoxBaseSplitView.swift in Sources */, DE44081D2A928F760091937A /* Divider.swift in Sources */, DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */, + DE94574B2AA0A70500B0B768 /* NetworkView.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, DE3FF36B2A978A57009C88EF /* WindowButtonViewController.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, diff --git a/Box42/Menubar/MenubarViewController.swift b/Box42/Menubar/MenubarViewController.swift index 56f60e5..495d7df 100644 --- a/Box42/Menubar/MenubarViewController.swift +++ b/Box42/Menubar/MenubarViewController.swift @@ -9,7 +9,7 @@ import Foundation import AppKit class MenubarViewController: NSViewController { - var popover = NSPopover() + var popover: NSPopover! = NSPopover() var statusBarVM = StatusBarViewModel() lazy var eventMonitor: EventMonitor = self.setupEventMonitor() var boxWindowController: BoxWindowController? diff --git a/Box42/Preferences/View/Funtion/BatteryView.swift b/Box42/Preferences/View/Funtion/BatteryView.swift new file mode 100644 index 0000000..030c56e --- /dev/null +++ b/Box42/Preferences/View/Funtion/BatteryView.swift @@ -0,0 +1,61 @@ +// +// BatteryView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class BatteryView: NSView { + + private let currentStateLabel: NSTextField = NSTextField(labelWithString: "현재 상태 (%):") + private let powerSourceLabel: NSTextField = NSTextField(labelWithString: "Power Source:") + private let maxCapacityLabel: NSTextField = NSTextField(labelWithString: "Max Capacity:") + private let cycleCountLabel: NSTextField = NSTextField(labelWithString: "Cycle Count:") + private let temperatureLabel: NSTextField = NSTextField(labelWithString: "Temperature:") + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + addSubview(currentStateLabel) + addSubview(powerSourceLabel) + addSubview(maxCapacityLabel) + addSubview(cycleCountLabel) + addSubview(temperatureLabel) + + // SnapKit 레이아웃 설정 + currentStateLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(10) + make.left.equalToSuperview().offset(10) + } + + powerSourceLabel.snp.makeConstraints { make in + make.top.equalTo(currentStateLabel.snp.bottom).offset(10) + make.left.equalTo(currentStateLabel) + } + + maxCapacityLabel.snp.makeConstraints { make in + make.top.equalTo(powerSourceLabel.snp.bottom).offset(10) + make.left.equalTo(currentStateLabel) + } + + cycleCountLabel.snp.makeConstraints { make in + make.top.equalTo(maxCapacityLabel.snp.bottom).offset(10) + make.left.equalTo(currentStateLabel) + } + + temperatureLabel.snp.makeConstraints { make in + make.top.equalTo(cycleCountLabel.snp.bottom).offset(10) + make.left.equalTo(currentStateLabel) + } + } +} diff --git a/Box42/Preferences/View/Funtion/CPUView.swift b/Box42/Preferences/View/Funtion/CPUView.swift new file mode 100644 index 0000000..74a296b --- /dev/null +++ b/Box42/Preferences/View/Funtion/CPUView.swift @@ -0,0 +1,84 @@ +// +// CPUView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class CPUView: NSView { + + // UI Elements + private let usageLabel: NSTextField = { + let label = NSTextField(labelWithString: "Usage: ") + label.font = NSFont.systemFont(ofSize: 16) + return label + }() + + private let systemLabel: NSTextField = { + let label = NSTextField(labelWithString: "System: ") + label.font = NSFont.systemFont(ofSize: 16) + return label + }() + + private let userLabel: NSTextField = { + let label = NSTextField(labelWithString: "User: ") + label.font = NSFont.systemFont(ofSize: 16) + return label + }() + + private let idleLabel: NSTextField = { + let label = NSTextField(labelWithString: "Idle: ") + label.font = NSFont.systemFont(ofSize: 16) + return label + }() + + // Initialize view + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupViews() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + } + + // Setup UI elements + private func setupViews() { + addSubview(usageLabel) + addSubview(systemLabel) + addSubview(userLabel) + addSubview(idleLabel) + + usageLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(16) + make.leading.equalToSuperview().offset(16) + } + + systemLabel.snp.makeConstraints { make in + make.top.equalTo(usageLabel.snp.bottom).offset(16) + make.leading.equalTo(usageLabel.snp.leading) + } + + userLabel.snp.makeConstraints { make in + make.top.equalTo(systemLabel.snp.bottom).offset(16) + make.leading.equalTo(systemLabel.snp.leading) + } + + idleLabel.snp.makeConstraints { make in + make.top.equalTo(userLabel.snp.bottom).offset(16) + make.leading.equalTo(userLabel.snp.leading) + } + } + + // Update data + func updateData(usage: String, system: String, user: String, idle: String) { + usageLabel.stringValue = "Usage: \(usage)" + systemLabel.stringValue = "System: \(system)" + userLabel.stringValue = "User: \(user)" + idleLabel.stringValue = "Idle: \(idle)" + } +} diff --git a/Box42/Preferences/View/Funtion/IconSettingView.swift b/Box42/Preferences/View/Funtion/IconSettingView.swift new file mode 100644 index 0000000..4993aa1 --- /dev/null +++ b/Box42/Preferences/View/Funtion/IconSettingView.swift @@ -0,0 +1,113 @@ +// +// IconSettingView.swift +// Box42 +// +// Created by Your Name on 8/31/23. +// + +import AppKit +import SnapKit + +class CustomSwitch: NSButton { + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setButtonType(.pushOnPushOff) + self.title = "" + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + if self.state == .on { + // On 상태일 때의 색상 및 디자인 설정 + NSColor.green.setFill() + dirtyRect.fill() + } else { + // Off 상태일 때의 색상 및 디자인 설정 + NSColor.red.setFill() + dirtyRect.fill() + } + } +} + +class IconSettingView: NSView { + private let iconSettingLabel: NSTextField = { + let label = NSTextField(labelWithString: "아이콘 설정") + label.font = NSFont.systemFont(ofSize: 20) + label.isEditable = false + label.isSelectable = false + return label + }() + + private let flipLabel: NSTextField = { + let label = NSTextField(labelWithString: "아이콘 좌우반전") + return label + }() + + private let flipSwitch: NSSwitch = { + let flipSwitch = NSSwitch() +// flipSwitch.wantsLayer = true +// flipSwitch.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor + + return flipSwitch + }() + + private let speedUpLabel: NSTextField = { + let label = NSTextField(labelWithString: "CPU가 느릴때 더 빠르게") + return label + }() + + private let speedUpSwitch: CustomSwitch = { + let speedUpSwitch = CustomSwitch() + return speedUpSwitch + + }() + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + self.addSubview(iconSettingLabel) + self.addSubview(flipLabel) + self.addSubview(flipSwitch) + self.addSubview(speedUpLabel) + self.addSubview(speedUpSwitch) + + iconSettingLabel.snp.makeConstraints { (make) in + make.top.equalToSuperview().offset(10) + make.left.equalToSuperview().offset(10) + make.right.equalToSuperview().offset(-10) + } + + flipLabel.snp.makeConstraints { (make) in + make.top.equalTo(iconSettingLabel.snp.bottom).offset(20) + make.left.equalToSuperview().offset(10) + } + + flipSwitch.snp.makeConstraints { (make) in + make.centerY.equalTo(flipLabel) + make.left.equalTo(flipLabel.snp.right).offset(10) + } + + speedUpLabel.snp.makeConstraints { (make) in + make.top.equalTo(flipLabel.snp.bottom).offset(20) + make.left.equalToSuperview().offset(10) + } + + speedUpSwitch.snp.makeConstraints { (make) in + make.centerY.equalTo(speedUpLabel) + make.left.equalTo(speedUpLabel.snp.right).offset(10) + } + } +} diff --git a/Box42/Preferences/View/Funtion/MemoryView.swift b/Box42/Preferences/View/Funtion/MemoryView.swift new file mode 100644 index 0000000..b731e79 --- /dev/null +++ b/Box42/Preferences/View/Funtion/MemoryView.swift @@ -0,0 +1,75 @@ +// +// MemoryView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class MemoryView: NSView { + + private let physicalMemoryLabel: NSTextField = NSTextField(labelWithString: "물리적 메모리:") + private let usedMemoryLabel: NSTextField = NSTextField(labelWithString: "사용된 메모리:") + private let cachedFilesLabel: NSTextField = NSTextField(labelWithString: "캐시된 파일:") + private let usedSwapLabel: NSTextField = NSTextField(labelWithString: "사용된 스왑 공간:") + private let appMemoryLabel: NSTextField = NSTextField(labelWithString: "앱 메모리:") + private let wiredMemoryLabel: NSTextField = NSTextField(labelWithString: "와이어드 메모리:") + private let compressedLabel: NSTextField = NSTextField(labelWithString: "압축됨:") + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + addSubview(physicalMemoryLabel) + addSubview(usedMemoryLabel) + addSubview(cachedFilesLabel) + addSubview(usedSwapLabel) + addSubview(appMemoryLabel) + addSubview(wiredMemoryLabel) + addSubview(compressedLabel) + + // SnapKit 레이아웃 설정 + physicalMemoryLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(10) + make.left.equalToSuperview().offset(10) + } + + usedMemoryLabel.snp.makeConstraints { make in + make.top.equalTo(physicalMemoryLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + + cachedFilesLabel.snp.makeConstraints { make in + make.top.equalTo(usedMemoryLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + + usedSwapLabel.snp.makeConstraints { make in + make.top.equalTo(cachedFilesLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + + appMemoryLabel.snp.makeConstraints { make in + make.top.equalTo(usedSwapLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + + wiredMemoryLabel.snp.makeConstraints { make in + make.top.equalTo(appMemoryLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + + compressedLabel.snp.makeConstraints { make in + make.top.equalTo(wiredMemoryLabel.snp.bottom).offset(10) + make.left.equalTo(physicalMemoryLabel) + } + } +} diff --git a/Box42/Preferences/View/Funtion/NetworkView.swift b/Box42/Preferences/View/Funtion/NetworkView.swift new file mode 100644 index 0000000..342d68d --- /dev/null +++ b/Box42/Preferences/View/Funtion/NetworkView.swift @@ -0,0 +1,54 @@ +// +// NetworkView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class NetworkView: NSView { + + private let connectionTypeLabel: NSTextField = NSTextField(labelWithString: "Connection Type:") + private let localIPLabel: NSTextField = NSTextField(labelWithString: "Local IP:") + private let uploadLabel: NSTextField = NSTextField(labelWithString: "Upload:") + private let downloadLabel: NSTextField = NSTextField(labelWithString: "Download:") + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupView() { + addSubview(connectionTypeLabel) + addSubview(localIPLabel) + addSubview(uploadLabel) + addSubview(downloadLabel) + + // SnapKit을 이용한 레이아웃 설정 + connectionTypeLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(10) + make.left.equalToSuperview().offset(10) + } + + localIPLabel.snp.makeConstraints { make in + make.top.equalTo(connectionTypeLabel.snp.bottom).offset(10) + make.left.equalTo(connectionTypeLabel) + } + + uploadLabel.snp.makeConstraints { make in + make.top.equalTo(localIPLabel.snp.bottom).offset(10) + make.left.equalTo(connectionTypeLabel) + } + + downloadLabel.snp.makeConstraints { make in + make.top.equalTo(uploadLabel.snp.bottom).offset(10) + make.left.equalTo(connectionTypeLabel) + } + } +} diff --git a/Box42/Preferences/View/Funtion/NotificationSettingView.swift b/Box42/Preferences/View/Funtion/NotificationSettingView.swift new file mode 100644 index 0000000..978df63 --- /dev/null +++ b/Box42/Preferences/View/Funtion/NotificationSettingView.swift @@ -0,0 +1,60 @@ +// +// NotificationSettingView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class NotificationSettingView: NSView { + + // Create a label for the title + let titleLabel: NSTextField = { + let label = NSTextField(labelWithString: "Box 알림 설정") + label.font = NSFont.systemFont(ofSize: 20) + label.isEditable = false + label.isSelectable = false + return label + }() + + // Create a switch button + let toggleButton: NSButton = { + let toggle = NSButton(checkboxWithTitle: "알림 활성화", target: nil, action: #selector(toggleChanged)) + return toggle + }() + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setupViews() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.setupViews() + } + + private func setupViews() { + // Add titleLabel to the view + addSubview(titleLabel) + titleLabel.snp.makeConstraints { make in + make.top.equalTo(self).offset(20) + make.centerX.equalTo(self) + } + + // Add toggleButton to the view + addSubview(toggleButton) + toggleButton.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(20) + make.centerX.equalTo(self) + } + + toggleButton.target = self + toggleButton.action = #selector(toggleChanged) + } + + @objc private func toggleChanged(_ sender: NSButton) { + print("Notification is now \(sender.state == .on ? "enabled" : "disabled")") + } +} diff --git a/Box42/Preferences/View/Funtion/RequestAccessView.swift b/Box42/Preferences/View/Funtion/RequestAccessView.swift index 0062579..b95e905 100644 --- a/Box42/Preferences/View/Funtion/RequestAccessView.swift +++ b/Box42/Preferences/View/Funtion/RequestAccessView.swift @@ -9,6 +9,13 @@ import AppKit import SnapKit class RequestAccessView: NSView { + private let requestAccessLabel: NSTextField = { + let label = NSTextField(labelWithString: "Request Access") + label.font = NSFont.systemFont(ofSize: 20) + label.isEditable = false + label.isSelectable = false + return label + }() var requestAccessTextField: NSTextField = NSTextField() var grantAccessButton: NSButton = NSButton() var revokeAccessButton: NSButton = NSButton() @@ -21,6 +28,7 @@ class RequestAccessView: NSView { self.layer?.cornerRadius = 13 // Add subviews + self.addSubview(requestAccessLabel) self.addSubview(requestAccessTextField) self.addSubview(grantAccessButton) self.addSubview(revokeAccessButton) @@ -79,8 +87,14 @@ class RequestAccessView: NSView { } func textfieldConstraints() { + requestAccessLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(10) + make.leading.equalToSuperview().offset(17) + make.trailing.equalToSuperview().offset(-17) + } + requestAccessTextField.snp.makeConstraints { make in - make.top.equalToSuperview().offset(10) + make.top.equalTo(requestAccessLabel.snp.bottom).offset(10) make.leading.equalToSuperview().offset(17) make.trailing.equalToSuperview().offset(-17) } diff --git a/Box42/Preferences/View/Funtion/ShortcutSettingView.swift b/Box42/Preferences/View/Funtion/ShortcutSettingView.swift new file mode 100644 index 0000000..b5e215d --- /dev/null +++ b/Box42/Preferences/View/Funtion/ShortcutSettingView.swift @@ -0,0 +1,105 @@ +// +// ShortcutSettingView.swift +// Box42 +// +// Created by Chanhee Kim on 8/31/23. +// + +import AppKit +import SnapKit + +class ShortcutSettingView: NSView { + + // Create a label for the title + let titleLabel: NSTextField = { + let label = NSTextField(labelWithString: "앱 내부 단축키 설정") + label.font = NSFont.systemFont(ofSize: 20) + label.isEditable = false + label.isSelectable = false + return label + }() + + // Create an array of labels and text fields for various shortcut settings + let shortcutSettings: [(label: String, defaultKey: String)] = [ + ("앱 Show 단축키 설정", "Middle Mouse"), + ("Pin Box 단축키 설정", "P"), + ("퀵슬롯 1 설정", "Q"), + ("퀵슬롯 2 설정", "W"), + ("퀵슬롯 3 설정", "E"), + ("퀵슬롯 4 설정", "R"), + ("퀵슬롯 5 설정", "A"), + ("퀵슬롯 6 설정", "S"), + ("퀵슬롯 7 설정", "D"), + ("퀵슬롯 8 설정", "F") + ] + + lazy var stackView: NSStackView = { + let stackView = NSStackView() + stackView.orientation = .vertical + stackView.distribution = .fillEqually + stackView.spacing = 20 + + var subStackView: NSStackView? + + for (index, (labelText, defaultKey)) in shortcutSettings.enumerated() { + let label = NSTextField(labelWithString: labelText) + label.isEditable = false + label.isSelectable = false + let textField = NSTextField() + textField.placeholderString = defaultKey + + if index == 0 || index == 1 { + let innerStackView = NSStackView(views: [label, textField]) + innerStackView.distribution = .fillProportionally + stackView.addArrangedSubview(innerStackView) + } else { + if index == 2 || index == 6 { + subStackView = NSStackView() + subStackView?.orientation = .horizontal + subStackView?.distribution = .fillEqually + subStackView?.spacing = 20 + } + + let innerStackView = NSStackView(views: [label, textField]) + innerStackView.distribution = .fillProportionally + + subStackView?.addArrangedSubview(innerStackView) + + if index == 4 || index == 8 { + stackView.addArrangedSubview(subStackView!) + } + } + } + + return stackView + }() + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupViews() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + } + + private func setupViews() { + // Add titleLabel to the view + addSubview(titleLabel) + titleLabel.snp.makeConstraints { make in + make.top.equalTo(self).offset(20) + make.centerX.equalTo(self) + } + + // Add stackView to the view + addSubview(stackView) + stackView.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(20) + make.left.equalTo(self).offset(20) + make.right.equalTo(self).offset(-20) + } + } + + // Further actions like saving the shortcuts, adding validations can be implemented +} diff --git a/Box42/Preferences/View/Funtion/StorageView.swift b/Box42/Preferences/View/Funtion/StorageView.swift index 77650b6..9a72a30 100644 --- a/Box42/Preferences/View/Funtion/StorageView.swift +++ b/Box42/Preferences/View/Funtion/StorageView.swift @@ -4,6 +4,7 @@ // // Created by Chanhee Kim on 8/31/23. // + import AppKit import SnapKit diff --git a/Box42/Preferences/View/Table/PreferencesCell.swift b/Box42/Preferences/View/Table/PreferencesCell.swift index f9dfadb..d082b3d 100644 --- a/Box42/Preferences/View/Table/PreferencesCell.swift +++ b/Box42/Preferences/View/Table/PreferencesCell.swift @@ -10,22 +10,7 @@ import SnapKit class PreferencesCell: NSTableCellView { - var baseContainerView: NSView = { - let baseView = NSView() - baseView.wantsLayer = true - baseView.layer?.backgroundColor = NSColor.yellow.cgColor - return baseView - }() - override func awakeFromNib() { super.awakeFromNib() - self.setupViews() - } - - private func setupViews() { - self.addSubview(baseContainerView) - baseContainerView.snp.makeConstraints { make in - make.edges.equalToSuperview() - } } } diff --git a/Box42/Preferences/View/Table/PreferencesTableView.swift b/Box42/Preferences/View/Table/PreferencesTableView.swift index 2c0ec06..9c8119f 100644 --- a/Box42/Preferences/View/Table/PreferencesTableView.swift +++ b/Box42/Preferences/View/Table/PreferencesTableView.swift @@ -7,31 +7,52 @@ import AppKit import SnapKit -import Combine enum PreferencesCellList: CaseIterable { - case requestAccessView + case notifiactionSetting + case shortcutSetting + case iconSetting + case requestAccess case storage case cpu - case my + case memory + case battery + case network var height: CGFloat { switch self { - case .requestAccessView: - return 100.0 + case .notifiactionSetting: + return 120 + case .shortcutSetting: + return 220 + case .iconSetting: + return 150 + case .requestAccess: + return 200 case .storage: - return 300.0 + return 210.0 case .cpu: - return 40.0 - case .my: - return 50.0 + return 150 + case .memory: + return 160 + case .battery: + return 140 + case .network: + return 130 } } } class PreferencesTableView: NSTableView { + let notifiactionSettingView = NotificationSettingView() + let shortcutSettingView = ShortcutSettingView() + let iconSettingView = IconSettingView() let requestAccessView = RequestAccessView() let storageView = StorageView() + let cpuView = CPUView() + let memoryView = MemoryView() + let batteryView = BatteryView() + let networkView = NetworkView() func setup() { self.delegate = self @@ -42,7 +63,7 @@ class PreferencesTableView: NSTableView { column1.title = "Preferences" self.addTableColumn(column1) - self.selectionHighlightStyle = .none +// self.selectionHighlightStyle = .none } } @@ -52,16 +73,24 @@ extension PreferencesTableView: NSTableViewDelegate, NSTableViewDataSource { let allCases = PreferencesCellList.allCases if row >= 0 && row < allCases.count { switch allCases[row] { - case .requestAccessView: + case .notifiactionSetting: + return notifiactionSettingView + case .shortcutSetting: + return shortcutSettingView + case .iconSetting: + return iconSettingView + case .requestAccess: return requestAccessView case .storage: - return StorageView() + return storageView case .cpu: - // Return the view for the CPU cell - return NSView() // Placeholder - case .my: - // Return the view for the "my" cell - return NSView() // Placeholder + return cpuView + case .memory: + return memoryView + case .battery: + return batteryView + case .network: + return networkView } } return NSView() // Default view if out of bounds or undefined diff --git a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift index b965db8..9a55e20 100644 --- a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift +++ b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift @@ -8,7 +8,7 @@ import Foundation // Model -struct QuickSlotButtonModel { +struct QuickSlotButtonModel: Codable { let id: UUID var title: String var path: String? diff --git a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift index c5d60bc..b1b31be 100644 --- a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift +++ b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift @@ -41,7 +41,9 @@ class QuickSlotButtonCollectionViewController: NSViewController { func initializeCombine() { viewModel.$buttons .sink { [weak self] _ in - self?.quickSlotButtonCollectionView.reloadData() + DispatchQueue.main.async { + self?.quickSlotButtonCollectionView.reloadData() + } } .store(in: &cancellables) } diff --git a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift index d636599..568168d 100644 --- a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift +++ b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift @@ -13,7 +13,8 @@ class QuickSlotViewModel { @Published var buttons: [QuickSlotButtonModel] = [] private init() { - let button1 = QuickSlotButtonModel(title: QuickSlotUI.title.clean, + let button1 = QuickSlotButtonModel(id: UUID(uuidString: "550e8400-e29b-41d4-a716-446655440000")!, + title: QuickSlotUI.title.clean, path: Bundle.main.path(forResource: "cleanCache", ofType: "sh")) let button2 = QuickSlotButtonModel(title: QuickSlotUI.title.preferences) let button3 = QuickSlotButtonModel(title: QuickSlotUI.title.scripts) diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index d674746..7d2ae45 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -31,8 +31,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { WebViewManager.shared.getCookie() API.getUserProfile(WebViewManager.shared.getCookieWebKit) _ = QuickSlotViewModel.shared - API.getUserMeScripts(WebViewManager.shared.getCookieWebKit) - _ = ScriptViewModel.shared + _ = ScriptViewModel.shared // 초기화와 동시에 } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/Box42/Resources/Box42.entitlements b/Box42/Resources/Box42.entitlements index 1b4b0b0..acd60f5 100644 --- a/Box42/Resources/Box42.entitlements +++ b/Box42/Resources/Box42.entitlements @@ -6,6 +6,10 @@ com.apple.security.automation.apple-events + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + com.apple.security.device.camera com.apple.security.files.downloads.read-write diff --git a/Box42/Resources/Info.plist b/Box42/Resources/Info.plist index 59cd59d..4187051 100644 --- a/Box42/Resources/Info.plist +++ b/Box42/Resources/Info.plist @@ -2,6 +2,8 @@ + NSAppleEventsUsageDescription + This app needs access to control System Preferences. NSDocumentsFolderUsageDescription 원활한 앱 구동을 위해 유저 디렉토리의 권한을 요청합니다. NSAppTransportSecurity diff --git a/Box42/Scripts/Controller/ScriptsViewController.swift b/Box42/Scripts/Controller/ScriptsViewController.swift index e86f46d..ff06ef2 100644 --- a/Box42/Scripts/Controller/ScriptsViewController.swift +++ b/Box42/Scripts/Controller/ScriptsViewController.swift @@ -10,7 +10,7 @@ import Foundation class ScriptsViewController: NSViewController { var scriptsTableView: ScriptsTableView? - var viewModel: ScriptViewModel? = ScriptViewModel() { + var viewModel: ScriptViewModel? = ScriptViewModel.shared { didSet { scriptsTableView?.viewModel = viewModel } diff --git a/Box42/Scripts/Model/Scripts.swift b/Box42/Scripts/Model/Scripts.swift index a83a5c4..40d59fa 100644 --- a/Box42/Scripts/Model/Scripts.swift +++ b/Box42/Scripts/Model/Scripts.swift @@ -12,17 +12,19 @@ struct Scripts: Codable { } struct Script: Codable { - var id: UUID + var id: UUID? var name: String var description: String var path: String - var savedId: Int + var savedId: Int? + var userUuid: String? - init(name: String, description: String, path: String, savedId: Int) { - self.id = UUID() + init(id: UUID = UUID(), name: String, description: String, path: String, savedId: Int, userUuid: String?) { + self.id = id self.name = name self.description = description self.path = path self.savedId = savedId + self.userUuid = userUuid } } diff --git a/Box42/Scripts/View/Table/ScriptsTableView.swift b/Box42/Scripts/View/Table/ScriptsTableView.swift index 2d77ef0..ccb1343 100644 --- a/Box42/Scripts/View/Table/ScriptsTableView.swift +++ b/Box42/Scripts/View/Table/ScriptsTableView.swift @@ -12,14 +12,17 @@ import Combine class ScriptsTableView: NSTableView { var viewModel: ScriptViewModel? { didSet { + print("ViewModel has been set.") setupBindings() } } - + var cancellables: Set = [] private func setupBindings() { - viewModel?.$scripts.sink(receiveValue: { [weak self] _ in + print("Setting up bindings...") // 디버깅 로그 + viewModel?.$scripts.sink(receiveValue: { [weak self] newScripts in + print("Received new scripts: \(newScripts)") // 디버깅 로그 DispatchQueue.main.async { self?.reloadData() } diff --git a/Box42/Scripts/ViewModel/ScriptsViewModel.swift b/Box42/Scripts/ViewModel/ScriptsViewModel.swift index d81c86e..04a0a37 100644 --- a/Box42/Scripts/ViewModel/ScriptsViewModel.swift +++ b/Box42/Scripts/ViewModel/ScriptsViewModel.swift @@ -13,32 +13,33 @@ class ScriptViewModel: NSObject { @Published var scripts: [Script] = [] - override init() { + private override init() { self.scripts = [ Script(name: "cleanCache", description: "Cleaning cache", - path: Bundle.main.path(forResource: "cleanCache", ofType: "sh") ?? "", savedId: -1 ), - Script(name: "brewInGoinfre", - description: "Brew download in goinfre", - path: Bundle.main.path(forResource: "brewInGoinfre", ofType: "sh") ?? "", savedId: -1), - Script(name: "exportMacOSInfo", - description: "export setting MacOS Info", - path: Bundle.main.path(forResource: "exportMacOSInfo", ofType: "sh") ?? "", savedId: -1 ), - Script(name: "importMacOSInfo", - description: "import MacOS Info", - path: Bundle.main.path(forResource: "importMacOSInfo", ofType: "sh") ?? "", savedId: -1), - Script(name: "key Mapping", - description: "key Mapping", - path: Bundle.main.path(forResource: "keyMapping", ofType: "sh") ?? "", savedId: -1 ), - Script(name: "nodeInstall", - description: "node Install", - path: Bundle.main.path(forResource: "nodeInstall", ofType: "sh") ?? "", savedId: -1) + path: Bundle.main.path(forResource: "cleanCache", ofType: "sh") ?? "", savedId: -1 , userUuid: nil), +// Script(name: "brewInGoinfre", +// description: "Brew download in goinfre", +// path: Bundle.main.path(forResource: "brewInGoinfre", ofType: "sh") ?? "", savedId: -1, userUuid: nil), +// Script(name: "exportMacOSInfo", +// description: "export setting MacOS Info", +// path: Bundle.main.path(forResource: "exportMacOSInfo", ofType: "sh") ?? "", savedId: -1, userUuid: nil), +// Script(name: "importMacOSInfo", +// description: "import MacOS Info", +// path: Bundle.main.path(forResource: "importMacOSInfo", ofType: "sh") ?? "", savedId: -1, userUuid: nil), +// Script(name: "key Mapping", +// description: "key Mapping", +// path: Bundle.main.path(forResource: "keyMapping", ofType: "sh") ?? "", savedId: -1, userUuid: nil), +// Script(name: "nodeInstall", +// description: "node Install", +// path: Bundle.main.path(forResource: "nodeInstall", ofType: "sh") ?? "", savedId: -1, userUuid: nil) ] + API.initializeUserMeScripts(WebViewManager.shared.getCookieWebKit) } // Create - func addScript(name: String, description: String, path: String) { - let newScript = Script(name: name, description: description, path: path, savedId: -1) + func addScript(id: UUID = UUID(), name: String, description: String, path: String, savedId: Int, userUuid: String) { + let newScript = Script(id: UUID(), name: name, description: description, path: path, savedId: savedId, userUuid: userUuid) scripts.append(newScript) } @@ -61,16 +62,30 @@ class ScriptViewModel: NSObject { // Delete func deleteScript(id: UUID) { - // delete 요청 보내야함 보내고 성공하면 지우기 - scripts.removeAll(where: { $0.id == id }) - QuickSlotViewModel.shared.removeButton(id) + if let script = scripts.first(where: { $0.id == id }) { + API.deleteUserMeScripts(WebViewManager.shared.getCookieWebKit, savedId: script.savedId!) { result in + switch result { + case .success(_): + self.scripts.removeAll(where: { $0.id == id }) + QuickSlotViewModel.shared.removeButton(id) + + case .failure(let error): + print("Failed to delete script: \(error)") + } + } + } } - // 새로운 스크립트 배열로 교체하는 메서드 + // 새로운 스크립트 배열로 교체하는 메소드 func replaceScripts(with newScripts: [Script]) { self.scripts = newScripts } + // VM class 시작시 최초 1회 실행되는 메소드 + func setupScripts(with newScripts: [Script]) { + self.scripts += newScripts + } + // 스크립트안에서 해당하는 스크립트를 찾아서 quickslotVM에 추가 func quickSlotScript(id: UUID) { if let index = scripts.firstIndex(where: { $0.id == id }) { diff --git a/Box42/Shared/API/API.swift b/Box42/Shared/API/API.swift index f9cb069..5d709ef 100644 --- a/Box42/Shared/API/API.swift +++ b/Box42/Shared/API/API.swift @@ -26,9 +26,17 @@ class API { return } + let jsonString = String(data: data, encoding: .utf8) + print("Received JSON string:\n\(jsonString ?? "")") + do { + if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { + print("Received data:\n\(json)") + } + let decodedData = try JSONDecoder().decode(type, from: data) completion(.success(decodedData)) + } catch let jsonError { completion(.failure(jsonError)) } @@ -54,10 +62,9 @@ class API { completion(.failure(NSError(domain: "InvalidStatusCode", code: httpResponse.statusCode, userInfo: nil))) return } - completion(.success(data)) } task.resume() } - + } diff --git a/Box42/Shared/API/DeleteUserMeScript.swift b/Box42/Shared/API/DeleteUserMeScript.swift new file mode 100644 index 0000000..dc77f5c --- /dev/null +++ b/Box42/Shared/API/DeleteUserMeScript.swift @@ -0,0 +1,24 @@ +// +// DeleteUserMeScript.swift +// Box42 +// +// Created by Chanhee Kim on 9/2/23. +// + +import WebKit + +extension API { + // MARK: - Scripts DELETE: https://api.42box.kr/user-service/users/me/scripts/{savedId} + static func deleteUserMeScripts(_ webView: WKWebView, savedId: Int, completion: @escaping (Result) -> Void) { + let url = "https://api.42box.kr/user-service/users/me/scripts/\(savedId)" + + deleteDataFromAPI(withURL: url) { (result: Result) in + switch result { + case .success(_): + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } + } +} diff --git a/Box42/Shared/API/GetUserMeScripts.swift b/Box42/Shared/API/GetUserMeScripts.swift index 7fa7d15..cd09521 100644 --- a/Box42/Shared/API/GetUserMeScripts.swift +++ b/Box42/Shared/API/GetUserMeScripts.swift @@ -8,7 +8,7 @@ import WebKit extension API { - // MARK: - Scripts GET: https://api.42box.site/user-service/users/me/scripts + // MARK: - Scripts GET: https://api.42box.kr/user-service/users/me/scripts // result : scripts.shared 저장 static func getUserMeScripts(_ webView: WKWebView) { @@ -18,7 +18,7 @@ extension API { cookieStorage.setCookie(cookie) } - fetchDataFromAPI(withURL: "https://api.42box.site/user-service/users/me/scripts", forType: [Script].self) { (result: Result<[Script], Error>) in + fetchDataFromAPI(withURL: "https://api.42box.kr/user-service/users/me/scripts", forType: [Script].self) { (result: Result<[Script], Error>) in switch result { case .success(let scripts): print(">> MacOS Get :", scripts) @@ -31,4 +31,26 @@ extension API { } } } + + static func initializeUserMeScripts(_ webView: WKWebView) { + webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in + let cookieStorage = HTTPCookieStorage.shared + for cookie in cookies { + cookieStorage.setCookie(cookie) + } + + fetchDataFromAPI(withURL: "https://api.42box.kr/user-service/users/me/scripts", forType: [Script].self) { (result: Result<[Script], Error>) in + switch result { + case .success(let scripts): + print(">> MacOS Get :", scripts) + DispatchQueue.main.async { + ScriptViewModel.shared.setupScripts(with: scripts) + } + case .failure(let error): + print("Error: \(error)") + } + } + } + } + } diff --git a/Box42/Shared/API/GetUserProfile.swift b/Box42/Shared/API/GetUserProfile.swift index 1815669..f029f45 100644 --- a/Box42/Shared/API/GetUserProfile.swift +++ b/Box42/Shared/API/GetUserProfile.swift @@ -8,7 +8,7 @@ import WebKit extension API { - // MARK: - 유저 정보 (Back) GET: https://api.42box.site/user-service/users/me + // MARK: - 유저 정보 (Back) GET: https://api.42box.kr/user-service/users/me // result : 성공 UserProfile.shared 저장 static func getUserProfile(_ webView: WKWebView) { @@ -18,7 +18,7 @@ extension API { cookieStorage.setCookie(cookie) } - fetchDataFromAPI(withURL: "https://api.42box.site/user-service/users/me", forType: UserProfile.self) { (result: Result) in + fetchDataFromAPI(withURL: "https://api.42box.kr/user-service/users/me", forType: UserProfile.self) { (result: Result) in switch result { case .success(let userProfile): print(">> MacOS Get :", userProfile) @@ -30,40 +30,3 @@ extension API { } } } - -//static func getUserProfile(_ webView: WKWebView) { -// webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in -// let cookieStorage = HTTPCookieStorage.shared -// -// for cookie in cookies { -//// print("\(cookie.name) = \(cookie.value)") -// cookieStorage.setCookie(cookie) -// } -// -// var request = URLRequest(url: URL(string: "https://api.42box.site/user-service/users/me")!) -// request.httpShouldHandleCookies = true -// let task = URLSession.shared.dataTask(with: request) { (data, response, error) in -// if let error = error { -// print("Error: \(error)") -// return -// } -// -// guard let data = data else { -// print("No data received.") -// return -// } -// -// do { -// let userProfile = try JSONDecoder().decode(UserProfile.self, from: data) -// -// print(">> MacOS Get :", userProfile ) -// UserManager.shared.updateUserProfile(newProfile: userProfile) -// -// } catch let jsonError { -// print("JSON Parsing Error: \(jsonError)") -// } -// } -// task.resume() -// } -//} -// diff --git a/Box42/Shared/SecurityScopedResourceAccess.swift b/Box42/Shared/SecurityScopedResourceAccess.swift index a919d15..041b397 100644 --- a/Box42/Shared/SecurityScopedResourceAccess.swift +++ b/Box42/Shared/SecurityScopedResourceAccess.swift @@ -21,7 +21,7 @@ class SecurityScopedResourceAccess { static func accessResourceExecuteShellScript(scriptPath: String) { queue.async(flags: .barrier) { - var url: URL? = nil // 이 부분을 추가하여 url 변수의 스코프를 확장합니다. + var url: URL? = nil do { var staleBookmarkData = false guard let bookmarkData = self.bookmarkData else { @@ -40,7 +40,6 @@ class SecurityScopedResourceAccess { isAccessing = url?.startAccessingSecurityScopedResource() ?? false - // Perform work here if isAccessing { ExecuteScripts.executeShellScript(path: scriptPath) } @@ -49,9 +48,7 @@ class SecurityScopedResourceAccess { print("An error occurred: \(error)") } - // Cleanup if isAccessing { - // Make sure to match this with a call to startAccessingSecurityScopedResource() url?.stopAccessingSecurityScopedResource() } } diff --git a/Box42/Shared/User/UserProfile.swift b/Box42/Shared/User/UserProfile.swift index 839b5c7..ce4e8a8 100644 --- a/Box42/Shared/User/UserProfile.swift +++ b/Box42/Shared/User/UserProfile.swift @@ -5,6 +5,8 @@ // Created by Chanhee Kim on 8/28/23. // +import AppKit + struct UserProfile: Codable { let uuid: String let nickname: String @@ -14,6 +16,7 @@ struct UserProfile: Codable { let statusMessage: String let profileImageUrl: String let profileImagePath: String + let quickSlotList: [QuickSlotButtonModel] } struct URLItem: Codable { @@ -42,7 +45,9 @@ extension UserProfile { URLItem(name: "42gg", url: "https://42gg.kr/")], statusMessage: "hello 42Box!", profileImageUrl: "https://42box.kr/user_profile_image/a52671f9-fca9-43ad-b0c0-1c5360831cf2.png", - profileImagePath: "user_profile_image/a52671f9-fca9-43ad-b0c0-1c5360831cf2.png" + profileImagePath: "user_profile_image/a52671f9-fca9-43ad-b0c0-1c5360831cf2.png", + quickSlotList: [ QuickSlotButtonModel(id: UUID(uuidString: "550e8400-e29b-41d4-a716-446655440000")!, title: "cleanCache", path: Bundle.main.path(forResource: "cleanCache", ofType: "sh")), + ] ) } } diff --git a/Box42/WebView/Model/WebViewUI.swift b/Box42/WebView/Model/WebViewUI.swift index b3d5582..d5e4a63 100644 --- a/Box42/WebView/Model/WebViewUI.swift +++ b/Box42/WebView/Model/WebViewUI.swift @@ -9,9 +9,10 @@ import Foundation enum WebViewUI { enum transfer { - static let download = "download" + static let downloadScript = "downloadScript" + static let executeScript = "executeScript" + static let deleteScript = "deleteScript" static let icon = "icon" static let userProfile = "userProfile" - static let script = "script" } } diff --git a/Box42/WebView/WebView.swift b/Box42/WebView/WebView.swift index 80b8b3b..8521d2a 100644 --- a/Box42/WebView/WebView.swift +++ b/Box42/WebView/WebView.swift @@ -21,10 +21,11 @@ class WebView: WKWebView, WKScriptMessageHandler { configuration.userContentController = contentController super.init(frame: .zero, configuration: configuration) - contentController.add(self, name: WebViewUI.transfer.download) + contentController.add(self, name: WebViewUI.transfer.deleteScript) + contentController.add(self, name: WebViewUI.transfer.executeScript) + contentController.add(self, name: WebViewUI.transfer.downloadScript) contentController.add(self, name: WebViewUI.transfer.icon) contentController.add(self, name: WebViewUI.transfer.userProfile) - contentController.add(self, name: WebViewUI.transfer.script) self.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true self.configuration.preferences.javaScriptEnabled = true @@ -41,15 +42,12 @@ class WebView: WKWebView, WKScriptMessageHandler { // MARK: - Front Client 통신 extension WebView { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - // 스크립트 다운로드 - if message.name == WebViewUI.transfer.download, let downloadURLString = message.body as? String { - ScriptsFileManager.downloadFile(from: downloadURLString) - } + // 아이콘 정보 PUT: if message.name == WebViewUI.transfer.icon, let imgIconString = message.body as? String { icon.buttonImageChange(imgIconString) } - // 유저 정보 (Front)GET: https://api.42box.site/user-service/users/me + // 유저 정보 (Front)GET: https://api.42box.kr/user-service/users/me if message.name == WebViewUI.transfer.userProfile, let userProfileString = message.body as? String { let userProfileJson = userProfileString.data(using: .utf8) @@ -65,20 +63,58 @@ extension WebView { print("JSON decoding failed: \(error)") } } - - if message.name == WebViewUI.transfer.script, let scriptString = message.body as? String { - let scriptJson = scriptString.data(using: .utf8) + // 스크립트 다운로드 + if message.name == WebViewUI.transfer.downloadScript, let downloadScriptString = message.body as? String { + let scriptJson = downloadScriptString.data(using: .utf8) + print(String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") do { let decoder = JSONDecoder() - let downScript = try decoder.decode(Script.self, from: scriptJson!) - print(downScript) + let downloadString = try decoder.decode(Script.self, from: scriptJson!) + ScriptViewModel.shared.addScript(id: UUID(), name: downloadString.name, description: downloadString.description, path: downloadString.path, savedId: Int(downloadString.savedId ?? 0), userUuid: downloadString.userUuid!) + print(downloadString) } catch { print("JSON decoding failed: \(error)") } } + + // 스크립트 실행 + if message.name == WebViewUI.transfer.executeScript, let executeScriptString = message.body as? String { + let scriptJson = executeScriptString.data(using: .utf8) + print(String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") + + do { + let decoder = JSONDecoder() + let executeScript = try decoder.decode(Script.self, from: scriptJson!) + print(String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") + + print(executeScript) + + ScriptsFileManager.downloadFile(from: "https://42box.kr/" + executeScript.path) + } catch { + print("JSON decoding failed: \(error)") + } + } + + // 스크립트 삭제 + if message.name == WebViewUI.transfer.deleteScript, let deleteScriptString = message.body as? String { + let scriptJson = deleteScriptString.data(using: .utf8) + print(String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") + + do { + let decoder = JSONDecoder() + let deleteScript = try decoder.decode(Script.self, from: scriptJson!) + print(String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") + + print(deleteScript) + + ScriptViewModel.shared.deleteScript(id: deleteScript.id!) + } catch { + print("JSON decoding failed: \(error)") + } + } } } diff --git a/Box42/WebView/WebViewManager.swift b/Box42/WebView/WebViewManager.swift index 18f0905..088c310 100644 --- a/Box42/WebView/WebViewManager.swift +++ b/Box42/WebView/WebViewManager.swift @@ -40,7 +40,7 @@ class WebViewManager: NSObject { } func getCookie() { - if let url = URL(string: "https://api.42box.site") { + if let url = URL(string: "https://api.42box.kr") { let request = URLRequest(url: url) getCookieWebKit.load(request) }