diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index 77df456..24e1b4d 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -7,7 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - 7E9B46922AA5C564009EB900 /* BookmarkEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E9B46912AA5C564009EB900 /* BookmarkEditorView.swift */; }; + 64D699FE2AA5F69900EEF7BC /* BookmarkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D699FD2AA5F69900EEF7BC /* BookmarkModel.swift */; }; + 64D69A012AA5F97B00EEF7BC /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D699F72AA5F5C100EEF7BC /* BookmarkViewModel.swift */; }; + 7E9B46922AA5C564009EB900 /* BookmarkEditorTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E9B46912AA5C564009EB900 /* BookmarkEditorTableView.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 */; }; @@ -115,6 +117,15 @@ DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */; }; DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */; }; DE98E8552A98EA7900F8744A /* WindowButtonUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */; }; + DE9B57562AA62723007B796C /* BookmarkTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B57552AA62723007B796C /* BookmarkTableView.swift */; }; + DE9B575A2AA629E4007B796C /* DraggableButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B57592AA629E4007B796C /* DraggableButton.swift */; }; + DE9B575E2AA62A54007B796C /* ButtonTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B575D2AA62A54007B796C /* ButtonTableCellView.swift */; }; + DE9B57672AA65B87007B796C /* PutUserMeUrlList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B57662AA65B87007B796C /* PutUserMeUrlList.swift */; }; + DE9B576C2AA6647F007B796C /* BookmarkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B576B2AA6647F007B796C /* BookmarkCell.swift */; }; + DE9B576F2AA664D1007B796C /* BookmarkCellManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B576E2AA664D1007B796C /* BookmarkCellManager.swift */; }; + DE9B57782AA66DCD007B796C /* BookmarkUpdateButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B57772AA66DCD007B796C /* BookmarkUpdateButton.swift */; }; + DE9B577C2AA66DEA007B796C /* BookmarkDeleteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B577B2AA66DEA007B796C /* BookmarkDeleteButton.swift */; }; + DE9B577F2AA66DF9007B796C /* BookmarkCreateButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B577E2AA66DF9007B796C /* BookmarkCreateButton.swift */; }; DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */; }; DEB862D42A85124500278FCD /* cleanCache.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D32A85124500278FCD /* cleanCache.sh */; }; DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; @@ -134,7 +145,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 7E9B46912AA5C564009EB900 /* BookmarkEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkEditorView.swift; sourceTree = ""; }; + 64D699F72AA5F5C100EEF7BC /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; + 64D699FD2AA5F69900EEF7BC /* BookmarkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkModel.swift; sourceTree = ""; }; + 7E9B46912AA5C564009EB900 /* BookmarkEditorTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkEditorTableView.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 = ""; }; @@ -244,6 +257,15 @@ DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RotateImage+NSImage.swift"; sourceTree = ""; }; DE98E8422A98DDFD00F8744A /* QuickSlotViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewController.swift; sourceTree = ""; }; DE98E8542A98EA7900F8744A /* WindowButtonUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowButtonUI.swift; sourceTree = ""; }; + DE9B57552AA62723007B796C /* BookmarkTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkTableView.swift; sourceTree = ""; }; + DE9B57592AA629E4007B796C /* DraggableButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableButton.swift; sourceTree = ""; }; + DE9B575D2AA62A54007B796C /* ButtonTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonTableCellView.swift; sourceTree = ""; }; + DE9B57662AA65B87007B796C /* PutUserMeUrlList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PutUserMeUrlList.swift; sourceTree = ""; }; + DE9B576B2AA6647F007B796C /* BookmarkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkCell.swift; sourceTree = ""; }; + DE9B576E2AA664D1007B796C /* BookmarkCellManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkCellManager.swift; sourceTree = ""; }; + DE9B57772AA66DCD007B796C /* BookmarkUpdateButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkUpdateButton.swift; sourceTree = ""; }; + DE9B577B2AA66DEA007B796C /* BookmarkDeleteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkDeleteButton.swift; sourceTree = ""; }; + DE9B577E2AA66DF9007B796C /* BookmarkCreateButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkCreateButton.swift; sourceTree = ""; }; DE9DA8132A97F20E001C0D3B /* ButtonGroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupViewController.swift; sourceTree = ""; }; DEB862D32A85124500278FCD /* cleanCache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cleanCache.sh; sourceTree = ""; }; DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; @@ -275,6 +297,32 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 64D699F62AA5F5AA00EEF7BC /* Bookmark */ = { + isa = PBXGroup; + children = ( + 64D699FF2AA5F69D00EEF7BC /* Model */, + 64D69A002AA5F6A100EEF7BC /* ViewModel */, + DE9B57542AA62704007B796C /* View */, + ); + path = Bookmark; + sourceTree = ""; + }; + 64D699FF2AA5F69D00EEF7BC /* Model */ = { + isa = PBXGroup; + children = ( + 64D699FD2AA5F69900EEF7BC /* BookmarkModel.swift */, + ); + path = Model; + sourceTree = ""; + }; + 64D69A002AA5F6A100EEF7BC /* ViewModel */ = { + isa = PBXGroup; + children = ( + 64D699F72AA5F5C100EEF7BC /* BookmarkViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; DE018BA62A5099F900FF0AA3 = { isa = PBXGroup; children = ( @@ -301,6 +349,7 @@ DE018C0E2A509C0C00FF0AA3 /* Menubar */, DE9DA8122A97F1E2001C0D3B /* ButtonGroup */, DE1F1A202A8B50CA00A88DD8 /* Main */, + 64D699F62AA5F5AA00EEF7BC /* Bookmark */, DE874F512A591EC600FC3B77 /* Preferences */, DEB862D22A8511D600278FCD /* Scripts */, DE018C0C2A509BDF00FF0AA3 /* Resources */, @@ -447,7 +496,6 @@ DE4408202A9297EE0091937A /* View */ = { isa = PBXGroup; children = ( - 7E9B46912AA5C564009EB900 /* BookmarkEditorView.swift */, DE1F1A1A2A8B50C500A88DD8 /* BoxContentsViewGroup.swift */, DE24E6372A8FE10300E29F5D /* BoxBaseSplitView.swift */, ); @@ -486,6 +534,7 @@ DEF0761A2AA33671005700E5 /* DeleteUserMeScript.swift */, DEF076292AA3B955005700E5 /* PutUserMeQuickSlot.swift */, DEF0762C2AA3C34C005700E5 /* GetUserMeQuickSlot.swift */, + DE9B57662AA65B87007B796C /* PutUserMeUrlList.swift */, ); path = API; sourceTree = ""; @@ -704,6 +753,38 @@ path = Model; sourceTree = ""; }; + DE9B57542AA62704007B796C /* View */ = { + isa = PBXGroup; + children = ( + DE9B57732AA666D3007B796C /* Button */, + DE9B57742AA666DD007B796C /* Editor */, + DE9B57552AA62723007B796C /* BookmarkTableView.swift */, + DE9B57592AA629E4007B796C /* DraggableButton.swift */, + DE9B575D2AA62A54007B796C /* ButtonTableCellView.swift */, + ); + path = View; + sourceTree = ""; + }; + DE9B57732AA666D3007B796C /* Button */ = { + isa = PBXGroup; + children = ( + DE9B57772AA66DCD007B796C /* BookmarkUpdateButton.swift */, + DE9B577B2AA66DEA007B796C /* BookmarkDeleteButton.swift */, + DE9B577E2AA66DF9007B796C /* BookmarkCreateButton.swift */, + ); + path = Button; + sourceTree = ""; + }; + DE9B57742AA666DD007B796C /* Editor */ = { + isa = PBXGroup; + children = ( + 7E9B46912AA5C564009EB900 /* BookmarkEditorTableView.swift */, + DE9B576B2AA6647F007B796C /* BookmarkCell.swift */, + DE9B576E2AA664D1007B796C /* BookmarkCellManager.swift */, + ); + path = Editor; + sourceTree = ""; + }; DE9DA8122A97F1E2001C0D3B /* ButtonGroup */ = { isa = PBXGroup; children = ( @@ -883,6 +964,7 @@ DEF076302AA3CF8A005700E5 /* QuickSlotItemLabel.swift in Sources */, DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */, DE98E83B2A98DB6000F8744A /* RotateImage+NSImage.swift in Sources */, + DE9B575E2AA62A54007B796C /* ButtonTableCellView.swift in Sources */, DE0A91982A8F977F00D1D6F1 /* ToolbarViewController.swift in Sources */, DEF076432AA48AF0005700E5 /* QuickSlotCellDeleteButton.swift in Sources */, DE9DA8142A97F20E001C0D3B /* ButtonGroupViewController.swift in Sources */, @@ -912,6 +994,7 @@ DE6332E42A9BB8F800DCFAF6 /* QuickSlotButtonCollectionViewController.swift in Sources */, DE9457062A9E69C100B0B768 /* ScriptNameLabel.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, + DE9B577F2AA66DF9007B796C /* BookmarkCreateButton.swift in Sources */, DE44080C2A924B520091937A /* BoxFunctionViewGroup.swift in Sources */, DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */, DEF0762A2AA3B955005700E5 /* PutUserMeQuickSlot.swift in Sources */, @@ -919,8 +1002,11 @@ DE77BBA22A9DDC40006CC98B /* ScriptsFileManager.swift in Sources */, DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, DE0A91862A8F889F00D1D6F1 /* RefreshPageViaToolbar.swift in Sources */, + DE9B577C2AA66DEA007B796C /* BookmarkDeleteButton.swift in Sources */, + DE9B575A2AA629E4007B796C /* DraggableButton.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE77BBA62A9DDF2B006CC98B /* WebView.swift in Sources */, + 64D69A012AA5F97B00EEF7BC /* BookmarkViewModel.swift in Sources */, DE0A91832A8F889000D1D6F1 /* GoHomePageViaToolbar().swift in Sources */, DE6332F22A9BCA2C00DCFAF6 /* QuickSlotScriptsLogicController.swift in Sources */, DE9457512AA0BE0F00B0B768 /* NotificationSettingView.swift in Sources */, @@ -928,8 +1014,9 @@ DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, DE78860C2A9C770300FE21DD /* ScriptsViewModel.swift in Sources */, DE0A91632A8E6A5400D1D6F1 /* Constants.swift in Sources */, - 7E9B46922AA5C564009EB900 /* BookmarkEditorView.swift in Sources */, + 7E9B46922AA5C564009EB900 /* BookmarkEditorTableView.swift in Sources */, DE7886172A9CCB3B00FE21DD /* UserProfile.swift in Sources */, + DE9B57782AA66DCD007B796C /* BookmarkUpdateButton.swift in Sources */, DE0A91902A8F88CA00D1D6F1 /* DisplayURLInToolbar.swift in Sources */, DE77BBCD2A9E0568006CC98B /* ExecuteScripts.swift in Sources */, DE9456F82A9E44FD00B0B768 /* IconController.swift in Sources */, @@ -950,8 +1037,10 @@ DE3FF3772A978AB8009C88EF /* WindowMinimizeButton.swift in Sources */, DE9457542AA0BF5200B0B768 /* ShortcutSettingView.swift in Sources */, DE4408022A923EB60091937A /* PinButtonView.swift in Sources */, + DE9B57672AA65B87007B796C /* PutUserMeUrlList.swift in Sources */, DE77BBE22A9E0F70006CC98B /* Scripts.swift in Sources */, DE78862D2A9D1ADE00FE21DD /* PreferencesCell.swift in Sources */, + DE9B576C2AA6647F007B796C /* BookmarkCell.swift in Sources */, DE9457572AA0C5C600B0B768 /* IconSettingView.swift in Sources */, DE0A91672A8E6CA700D1D6F1 /* WebViewManager.swift in Sources */, DE77BBF32A9E38DC006CC98B /* UserManager.swift in Sources */, @@ -964,10 +1053,12 @@ DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */, DE7886282A9D186700FE21DD /* ScriptsViewController.swift in Sources */, DEF0763D2AA48125005700E5 /* QuickSlotCell.swift in Sources */, + DE9B57562AA62723007B796C /* BookmarkTableView.swift in Sources */, DE4408052A923EC00091937A /* QuitButtonView.swift in Sources */, DE0A918A2A8F88A900D1D6F1 /* GoForwardInToolbar.swift in Sources */, DE1F1A1E2A8B50C500A88DD8 /* BoxButtonViewGroup.swift in Sources */, DEB862EB2A853F7F00278FCD /* BoxWindowController.swift in Sources */, + 64D699FE2AA5F69900EEF7BC /* BookmarkModel.swift in Sources */, DE0A918D2A8F88BC00D1D6F1 /* GoBackInToolbar.swift in Sources */, DE94574E2AA0B56200B0B768 /* CPUView.swift in Sources */, DE018BDD2A509AEB00FF0AA3 /* EventMonitor.swift in Sources */, @@ -982,6 +1073,7 @@ DE98E8432A98DDFD00F8744A /* QuickSlotViewController.swift in Sources */, DEF0762D2AA3C34C005700E5 /* GetUserMeQuickSlot.swift in Sources */, DE94574B2AA0A70500B0B768 /* NetworkView.swift in Sources */, + DE9B576F2AA664D1007B796C /* BookmarkCellManager.swift in Sources */, DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, DE3FF36B2A978A57009C88EF /* WindowButtonViewController.swift in Sources */, DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, diff --git a/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 009c162..19d4e8c 100644 --- a/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Box42.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,14 +1,16 @@ { - "pins" : [ - { - "identity" : "snapkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SnapKit/SnapKit.git", - "state" : { - "revision" : "f222cbdf325885926566172f6f5f06af95473158", - "version" : "5.6.0" + "object": { + "pins": [ + { + "package": "SnapKit", + "repositoryURL": "https://github.com/SnapKit/SnapKit.git", + "state": { + "branch": null, + "revision": "f222cbdf325885926566172f6f5f06af95473158", + "version": "5.6.0" + } } - } - ], - "version" : 2 + ] + }, + "version": 1 } diff --git a/Box42/Bookmark/Model/BookmarkModel.swift b/Box42/Bookmark/Model/BookmarkModel.swift new file mode 100644 index 0000000..0f8bdd5 --- /dev/null +++ b/Box42/Bookmark/Model/BookmarkModel.swift @@ -0,0 +1,21 @@ +// +// BookmarkModel.swift +// Box42 +// +// Created by Chan on 2023/09/04. +// + +struct URLList: Codable { + let urlList: [URLItem] +} + +struct URLItem: Codable { + let name: String + let url: String +} + +extension URLItem: Equatable { + static func ==(lhs: URLItem, rhs: URLItem) -> Bool { + return lhs.name == rhs.name && lhs.url == rhs.url + } +} diff --git a/Box42/Bookmark/View/BookmarkTableView.swift b/Box42/Bookmark/View/BookmarkTableView.swift new file mode 100644 index 0000000..7cdad6a --- /dev/null +++ b/Box42/Bookmark/View/BookmarkTableView.swift @@ -0,0 +1,196 @@ +//// +//// BookmarkTableView.swift +//// Box42 +//// +//// Created by Chanhee Kim on 9/4/23. +//// +// +//import AppKit +//import SnapKit +//import Combine +// +//class BookmarkTableView: NSTableView { +// var onButtonClicked: ((DraggableButton) -> Void)? +// +// var buttonTitleArray: [String] { +// return BookmarkViewModel.shared.bookMarkList.map { $0.name } +// } +// +// var urlArray: [String] { +// return BookmarkViewModel.shared.bookMarkList.map { $0.url } +// } +// +// var viewModel: BookmarkViewModel? { +// didSet { +// print("ViewModel has been set.") +// setupBindings() +// } +// } +// +// var cancellables: Set = [] +// +// private func setupBindings() { +// print("Setting up bindings...") // 디버깅 로그 +// viewModel?.$bookMarkList.sink(receiveValue: { [weak self] newScripts in +// print("Received new scripts: \(newScripts)") // 디버깅 로그 +// DispatchQueue.main.async { +// self?.reloadData() +// } +// }).store(in: &cancellables) +// } +// +// func setup() { +// self.delegate = self +// self.dataSource = self +// self.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) +// +// self.wantsLayer = true +// self.backgroundColor = NSColor(hex: "#E7E7E7") +// self.focusRingType = .none +// self.headerView = nil +// self.autoresizingMask = [.width, .height] +// self.selectionHighlightStyle = .none +// self.intercellSpacing = NSSize(width: 0, height: 0) +// self.setDraggingSourceOperationMask(.move, forLocal: true) +// +// let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Bookmark")) +// column.title = "" +// // column.width = 100 +// column.resizingMask = .autoresizingMask +// +// self.addTableColumn(column) +// } +//} +// +//extension BookmarkTableView: NSTableViewDelegate, NSTableViewDataSource { +// +// func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { +// if dropOperation == .above { +// return .move +// } else { +// return [] +// } +// } +// +// func tableView(_ aTableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool { +// guard let str = info.draggingPasteboard.string(forType: .string), let from = Int(str) else { +// return false +// } +// +// let to = (from < row) ? row - 1 : row +// let item = BookmarkViewModel.shared.bookMarkList[from] +// BookmarkViewModel.shared.bookMarkList.remove(at: from) +// BookmarkViewModel.shared.bookMarkList.insert(item, at: to) +// self.reloadData() +// +// for (_, subview) in self.subviews.enumerated() { +// guard let cellView = subview as? CustomTableCellView else { +// continue +// } +// +// cellView.button.title = buttonTitleArray[cellView.rowIndex] +// } +// +// return true +// } +// +// func numberOfRows(in tableView: NSTableView) -> Int { +// return BookmarkViewModel.shared.bookMarkList.count +// } +// +// func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { +// let cellView = ButtonTableCellView() +// cellView.rowIndex = row +// +// let button = DraggableButton(frame: NSRect(x: 0, y: 0, width: 300, height: 44)) +// button.tag = row +// button.bezelStyle = .inline +// button.isBordered = false +// button.title = "" +// button.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) +// button.target = self +// button.action = #selector(buttonClicked(_:)) +// button.delegate = self +// +// let label = NSTextField(frame: NSRect(x: 26 + 21 + 8, y: 25 / 2, width: button.bounds.width, height: button.bounds.height)) +// +// label.stringValue = buttonTitleArray[row] +// label.backgroundColor = .clear +// label.isBordered = false +// label.isEditable = false +// +// let attributes : [NSAttributedString.Key : Any] = +// [ +// NSAttributedString.Key.font : NSFont.systemFont(ofSize:18.0, weight: .light), +// NSAttributedString.Key.foregroundColor : NSColor.black, +// ] +// let attributedStringTitle = NSAttributedString(string: label.stringValue , attributes: +// attributes) +// label.attributedStringValue=attributedStringTitle +// button.addSubview(label) +// +// +// // let image = NSImage(named: NSImage.Name("bookmark-default")) +// // image?.size = NSSize(width: 21, height: 21) +// // button.image = image +// // button.imagePosition = .imageLeading +// // button.image?.alignmentRect = NSRect(x: 0, y: 0, width: 21, height: 21) +// +// let imageView = NSImageView(frame: NSRect(x: 26, y: 25 / 2, width: 21, height: 21)) +// imageView.image = NSImage(named: NSImage.Name("bookmark-default")) +// imageView.imageScaling = .scaleProportionallyUpOrDown +// imageView.imageAlignment = .alignCenter +// button.addSubview(imageView) +// +// +// +// cellView.addSubview(button) +// +// button.snp.makeConstraints { make in +// make.top.equalToSuperview().offset(2) +// make.leading.equalToSuperview() +// make.trailing.equalToSuperview() +// // make.width.equalTo(268) +// make.width.lessThanOrEqualTo(268) +// make.height.equalTo(44) +// } +// +// tableView.rowHeight = 50 +// +// if row == selectedRow { +// button.wantsLayer = true +// button.layer?.cornerRadius = 12 +// button.layer?.backgroundColor = NSColor.white.cgColor +// } else { +// button.wantsLayer = true +// button.layer?.cornerRadius = 12 +// button.layer?.backgroundColor = NSColor.clear.cgColor +// } +// +// return cellView +// } +// +// func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? { +// let pasteboardItem = NSPasteboardItem() +// pasteboardItem.setString(String(row), forType: .string) +// return pasteboardItem +// } +// +// func sendUpdatedDataToServer() { +// let urlList = zip(buttonTitleArray, urlArray).map { ["name": $0.0, "url": $0.1] } +// let jsonData = try? JSONSerialization.data(withJSONObject: ["urlList": urlList]) +// +// var request = URLRequest(url: URL(string:"https://api.42box.kr/user-service/users/me/url-list")!) +// request.httpMethod = "POST" +// request.httpBody = jsonData +// +// URLSession.shared.dataTask(with:request) { (data, response, error) in +// if error != nil{ +// print(error!.localizedDescription) +// } +// else{ +// print("Data posted successfully") +// } +// }.resume() +// } +//} diff --git a/Box42/Bookmark/View/Button/BookmarkCreateButton.swift b/Box42/Bookmark/View/Button/BookmarkCreateButton.swift new file mode 100644 index 0000000..2c246de --- /dev/null +++ b/Box42/Bookmark/View/Button/BookmarkCreateButton.swift @@ -0,0 +1,68 @@ +// +// BookmarkCreateButton.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit + +class BookmarkCreateButton: NSButton { + + init() { + super.init(frame: NSRect(x: 0, y: 0, width: 70, height: 40)) + + self.title = "북마크 추가" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.maximize + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.maximize + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.maximize + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + } +} diff --git a/Box42/Bookmark/View/Button/BookmarkDeleteButton.swift b/Box42/Bookmark/View/Button/BookmarkDeleteButton.swift new file mode 100644 index 0000000..9d94da9 --- /dev/null +++ b/Box42/Bookmark/View/Button/BookmarkDeleteButton.swift @@ -0,0 +1,68 @@ +// +// BookmarkDeleteButton.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit + +class BookmarkDeleteButton: NSButton { + + init() { + super.init(frame: NSRect(x: 0, y: 0, width: 53, height: 40)) + + self.title = "삭제" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.close + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.close + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.close + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + } +} diff --git a/Box42/Bookmark/View/Button/BookmarkUpdateButton.swift b/Box42/Bookmark/View/Button/BookmarkUpdateButton.swift new file mode 100644 index 0000000..f621e96 --- /dev/null +++ b/Box42/Bookmark/View/Button/BookmarkUpdateButton.swift @@ -0,0 +1,94 @@ +// +// BookmarkUpdateButton.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit + +class BookmarkUpdateButton: NSButton { + + init() { + super.init(frame: NSRect(x: 0, y: 0, width: 53, height: 40)) + + self.title = "변경하기" + self.isBordered = false + self.wantsLayer = true + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + + let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.toValue = WindowButtonUI.color.minimize + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.minimize + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius / 2 + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + let bgColorAnimation = CABasicAnimation(keyPath: "backgroundColor") + bgColorAnimation.fromValue = WindowButtonUI.color.minimize + bgColorAnimation.toValue = WindowButtonUI.color.opacityWhite + bgColorAnimation.duration = WindowButtonUI.animation.duration + + let cornerAnimation = CABasicAnimation(keyPath: "cornerRadius") + cornerAnimation.fromValue = WindowButtonUI.size.cornerRadius / 2 + cornerAnimation.toValue = WindowButtonUI.size.cornerRadius + cornerAnimation.duration = WindowButtonUI.animation.duration + + self.layer?.add(bgColorAnimation, forKey: "backgroundColorAnimation") + self.layer?.add(cornerAnimation, forKey: "cornerRadiusAnimation") + + self.layer?.backgroundColor = WindowButtonUI.color.opacityWhite + self.layer?.cornerRadius = WindowButtonUI.size.cornerRadius + } + + override func mouseDown(with event: NSEvent) { + super.mouseDown(with: event) + + // 윈도우의 크기와 위치 정보를 가져옴 + guard self.window != nil else { + return + } + if self.title == "퀵슬롯" { return } + // 현재 버튼의 위치를 윈도우 기준으로 변환 + let initialLocation = self.frame.origin + + // 윈도우의 왼쪽 아래 모서리를 최종 목표 위치로 설정 + let finalLocation = NSPoint(x: 0, y: 0) + + // 애니메이션 블록 + NSAnimationContext.runAnimationGroup({ context in + context.duration = 1 // 애니메이션 지속 시간 + + // 애니메이션 적용 + self.animator().setFrameOrigin(finalLocation) + }, completionHandler: { + // 애니메이션 완료 후, 버튼을 원래 위치로 되돌림 + self.setFrameOrigin(initialLocation) + }) + } +} diff --git a/Box42/Bookmark/View/ButtonTableCellView.swift b/Box42/Bookmark/View/ButtonTableCellView.swift new file mode 100644 index 0000000..1a4b2e1 --- /dev/null +++ b/Box42/Bookmark/View/ButtonTableCellView.swift @@ -0,0 +1,21 @@ +//// +//// ButtonTableCellView.swift +//// Box42 +//// +//// Created by Chanhee Kim on 9/5/23. +//// +// +//import AppKit +// +//class ButtonTableCellView: NSTableCellView { +// var button: NSButton! +// var deleteButton: NSButton! +// var rowIndex: Int! +// +// override func viewWillDraw() { +// super.viewWillDraw() +// self.frame.size.width = 268.0 +// self.frame = NSRect(x: self.frame.origin.x - 3, y: self.frame.origin.y, +// width: self.frame.size.width, height: self.frame.size.height) +// } +//} diff --git a/Box42/Bookmark/View/DraggableButton.swift b/Box42/Bookmark/View/DraggableButton.swift new file mode 100644 index 0000000..cf9b0ec --- /dev/null +++ b/Box42/Bookmark/View/DraggableButton.swift @@ -0,0 +1,105 @@ +// +// DraggableButton.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit + +class DraggableButton: NSButton, NSDraggingSource { + weak var delegate: BoxBaseContainerViewController? + var mouseDownEvent: NSEvent? + + func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation { + return .move + } + var initialMouseDownPoint: CGPoint? + + override func mouseDown(with event: NSEvent) { + print("mouseDown") + self.initialMouseDownPoint = event.locationInWindow + } + + override func mouseDragged(with event: NSEvent) { + guard let initialPoint = self.initialMouseDownPoint else { return } + + let distance = hypot( + initialPoint.x - event.locationInWindow.x, + initialPoint.y - event.locationInWindow.y) + + if distance > 3 { // 드래그로 판단하는 최소 거리. 필요에 따라 조절 가능합니다. + let pasteboardItem = NSPasteboardItem() + pasteboardItem.setString("\(self.tag)", forType: .string) + + let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem) + + // Create a snapshot of the button + let snapshot = self.snapshot() + + // Set the dragging frame and contents + draggingItem.setDraggingFrame(self.bounds, contents: snapshot) + + beginDraggingSession(with: [draggingItem], event: event, source: self) + + self.initialMouseDownPoint = nil + } + } + + override func mouseUp(with event: NSEvent) { + guard let initialPoint = self.initialMouseDownPoint else { return } + + let distance = hypot( + initialPoint.x - event.locationInWindow.x, + initialPoint.y - event.locationInWindow.y) + + if distance < 3 { // 클릭으로 판단하는 최대 거리. 필요에 따라 조절 가능합니다. + self.target?.perform(self.action, with: self) + } + + self.initialMouseDownPoint = nil + } + + func snapshot() -> NSImage? { + guard let bitmapRep = bitmapImageRepForCachingDisplay(in: bounds) else { return nil } + cacheDisplay(in: bounds, to: bitmapRep) + let image = NSImage(size: bounds.size) + image.addRepresentation(bitmapRep) + return image + } + + override func viewDidMoveToWindow() { + super.viewDidMoveToWindow() + + let trackingArea = NSTrackingArea( + rect: bounds, + options: [.mouseEnteredAndExited, .activeAlways], + owner: self, + userInfo: nil + ) + + addTrackingArea(trackingArea) + } + + override func mouseEntered(with event: NSEvent) { + super.mouseEntered(with: event) + + if self != delegate?.selectedButton { + wantsLayer = true + layer?.frame.size = CGSize(width: 268.0, height: 44.0) + layer?.cornerRadius = 12 + layer?.backgroundColor = NSColor(red: 0.848, green: 0.848, blue: 0.848, alpha: 1).cgColor + } + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + + if self != delegate?.selectedButton { + wantsLayer = true + layer?.frame.size = CGSize(width: 268.0, height: 44.0) + layer?.cornerRadius = 12 + layer?.backgroundColor = NSColor.clear.cgColor + } + } +} diff --git a/Box42/Bookmark/View/Editor/BookmarkCell.swift b/Box42/Bookmark/View/Editor/BookmarkCell.swift new file mode 100644 index 0000000..7e0fc27 --- /dev/null +++ b/Box42/Bookmark/View/Editor/BookmarkCell.swift @@ -0,0 +1,96 @@ +// +// BookmarkCell.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit +import SnapKit + +class BookmarkCell: NSTableCellView { + var nameLabel: NSTextField = NSTextField() + var descriptionLabel: NSTextField = NSTextField() + var deleteButton: BookmarkDeleteButton = BookmarkDeleteButton() + var quickSlotButton: BookmarkUpdateButton = BookmarkUpdateButton() + + var viewModel: BookmarkViewModel? + var urlitem: URLItem? + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + addSubview(nameLabel) + addSubview(descriptionLabel) + addSubview(quickSlotButton) + addSubview(deleteButton) + + nameLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(16) + make.width.lessThanOrEqualTo(200).priority(.high) + } + + deleteButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-16) + make.width.equalTo(53) + make.height.equalTo(40) + } + + quickSlotButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalTo(deleteButton.snp.left).offset(-8) + make.width.equalTo(53) + make.height.equalTo(40) + } + + descriptionLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalTo(nameLabel.snp.right).offset(8) + make.right.lessThanOrEqualTo(quickSlotButton.snp.left).offset(-8) + make.width.greaterThanOrEqualTo(100).priority(.low) // 최소 너비와 낮은 우선순위 설정 + } + } + + + + func configure(with urlitem: URLItem, viewModel: BookmarkViewModel?) { + self.urlitem = urlitem + self.viewModel = viewModel + nameLabel.stringValue = urlitem.name + descriptionLabel.stringValue = urlitem.url + + deleteButton.target = self + deleteButton.action = #selector(deleteButtonClicked) + + quickSlotButton.target = self + quickSlotButton.action = #selector(quickSlotButtonclicked) + + } + + @objc func deleteButtonClicked() { + if let deleteItem = urlitem { + BookmarkViewModel.shared.deleteBookmark(item: deleteItem) + } + } + + @objc func quickSlotButtonclicked() { + if let tableView = self.superview as? NSTableView { + let rowIndex = tableView.row(for: self) + print("현재 셀의 index: \(rowIndex)") + + if let updateItem = urlitem { + print(rowIndex, updateItem) +// BookmarkViewModel.shared.updateBookmark(rowIndex, item: updateItem) + } + } + } +} diff --git a/Box42/Bookmark/View/Editor/BookmarkCellManager.swift b/Box42/Bookmark/View/Editor/BookmarkCellManager.swift new file mode 100644 index 0000000..a312395 --- /dev/null +++ b/Box42/Bookmark/View/Editor/BookmarkCellManager.swift @@ -0,0 +1,67 @@ +// +// BookmarkCellManager.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import AppKit +import SnapKit + +class BookmarkCellManager: NSTableCellView { + var nameLabel: NSTextField = NSTextField() + var descriptionLabel: NSTextField = NSTextField() + var excuteButton: BookmarkCreateButton = BookmarkCreateButton() + + var viewModel: BookmarkViewModel? + var urlitem: URLItem? + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + addSubview(nameLabel) + addSubview(descriptionLabel) + addSubview(excuteButton) + + nameLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(16) + make.width.lessThanOrEqualTo(200).priority(.high) // 최대 너비와 우선순위 설정 + } + + excuteButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-16) + make.width.equalTo(150) + make.height.equalTo(40) + } + + descriptionLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalTo(nameLabel.snp.right).offset(8) + make.right.lessThanOrEqualTo(excuteButton.snp.left).offset(-8) + make.width.greaterThanOrEqualTo(100).priority(.low) // 최소 너비와 낮은 우선순위 설정 + } + } + + func configure(with urlitem: URLItem, viewModel: BookmarkViewModel?) { + self.urlitem = urlitem + self.viewModel = viewModel + nameLabel.stringValue = urlitem.name + descriptionLabel.stringValue = urlitem.url + + excuteButton.target = self + excuteButton.action = #selector(excuteButtonClicked) + } + + @objc func excuteButtonClicked() { + BookmarkViewModel.shared.addBookmark(item: URLItem(name: nameLabel.stringValue, url: descriptionLabel.stringValue)) + } +} diff --git a/Box42/Bookmark/View/Editor/BookmarkEditorTableView.swift b/Box42/Bookmark/View/Editor/BookmarkEditorTableView.swift new file mode 100644 index 0000000..e0db761 --- /dev/null +++ b/Box42/Bookmark/View/Editor/BookmarkEditorTableView.swift @@ -0,0 +1,75 @@ +// +// BookmarkEditorTableView.swift +// Box42 +// +// Created by Dasol on 2023/09/04. +// + +import AppKit +import SnapKit +import Combine + +class BookmarkEditorTableView: NSTableView { + var viewModel: BookmarkViewModel? = BookmarkViewModel.shared + var cancellables: Set = [] + + func setup() { + self.delegate = self + self.dataSource = self + + let column1 = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("BookmarkEditorTableView")) + column1.width = 100.0 + column1.title = "BookmarkEditorTableView" + self.addTableColumn(column1) + + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.lightGray.cgColor + self.layer?.cornerRadius = 20 + } + + func setupBindings() { + viewModel?.$bookMarkList + .sink { [weak self] _ in + self?.reloadData() + } + .store(in: &cancellables) + } +} + +extension BookmarkEditorTableView: NSTableViewDelegate, NSTableViewDataSource { + func getCellForRow(at row: Int) -> NSView { + guard let viewModel = viewModel else { + return NSView() + } + + if row < viewModel.bookMarkList.count { + return getBookmarkCell(for: viewModel.bookMarkList[row], viewModel: viewModel) + } else { + // MARK: - 다음 버전에 추가 예정 + return getBookmarkCellManager() + } + } + + private func getBookmarkCell(for urlitem: URLItem, viewModel: BookmarkViewModel) -> BookmarkCell { + let cell = BookmarkCell(frame: .zero) + cell.configure(with: urlitem, viewModel: viewModel) + return cell + } + + private func getBookmarkCellManager() -> BookmarkCellManager { + let scriptCellManger = BookmarkCellManager(frame: .zero) + return scriptCellManger + } + + func numberOfRows(in tableView: NSTableView) -> Int { + return (viewModel?.bookMarkList.count ?? 0) + 1 + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + getCellForRow(at: row) + } + + func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { + return 44.0 + } +} diff --git a/Box42/Bookmark/ViewModel/BookmarkViewModel.swift b/Box42/Bookmark/ViewModel/BookmarkViewModel.swift new file mode 100644 index 0000000..b2c452e --- /dev/null +++ b/Box42/Bookmark/ViewModel/BookmarkViewModel.swift @@ -0,0 +1,105 @@ +// +// BookmarkViewModel.swift +// Box42 +// +// Created by Chan on 2023/09/04. +// + +import AppKit +import Combine + +class BookmarkViewModel: NSObject { + static let shared = BookmarkViewModel() + + @Published var bookMarkList: [URLItem] = [] + + private override init() { + self.bookMarkList = [URLItem(name: "42Box", url: "https://42box.kr/"), + URLItem(name: "23Coaltheme", url: "https://42box.github.io/front-end/"), + URLItem(name: "loopback", url: "http://127.0.0.1:3000/"), + URLItem(name: "Box 42", url: "https://42box.github.io/front-end/#/box"), + URLItem(name: "Intra 42", url: "https://intra.42.fr"), + URLItem(name: "Jiphyeonjeon", url: "https://42library.kr"), + URLItem(name: "42STAT", url: "https://stat.42seoul.kr/home"), + URLItem(name: "24Hane", url: "https://24hoursarenotenough.42seoul.kr"), + URLItem(name: "80kCoding", url: "https://80000coding.oopy.io"), + URLItem(name: "where42", url: "https://www.where42.kr"), + URLItem(name: "cabi", url: "https://cabi.42seoul.io/"), + URLItem(name: "42gg", url: "https://42gg.kr/")] + } + + // Create + func addBookmarkByFront(item: URLItem) { + bookMarkList.append(item) + loadWebView(item.name, item.url) + } + + // Create + func addBookmark(item: URLItem) { + bookMarkList.append(item) + loadWebView(item.name, item.url) + + let body = URLList(urlList: bookMarkList) + API.putUserMeUrlList(urlList: body) { result in + switch result { + case .success(_): + print("Successfully updated the scripts.") // 혹은 사용자에게 보여줄 알림 추가 + case .failure(let error): + print("Failed to update scripts: \(error.localizedDescription)") // 혹은 사용자에게 보여줄 알림 추가 + } + } + } + + func updateBookmark(index: Int, item: URLItem) { + WebViewManager.shared.list[item.name]?.navigationDelegate = nil + WebViewManager.shared.list[item.name]?.stopLoading() + WebViewManager.shared.list[item.name] = nil + bookMarkList[index] = item + loadWebView(item.name, item.url) + } + + // Delete + func deleteBookmark(item: URLItem) { + WebViewManager.shared.list[item.name]?.navigationDelegate = nil + WebViewManager.shared.list[item.name]?.stopLoading() + WebViewManager.shared.list[item.name] = nil + self.bookMarkList.removeAll(where: { $0 == item }) + } + + // 새로운 북마크 배열로 교체하는 메소드 + func replaceBookMarkList(with newBookMarkList: [URLItem]) { + DispatchQueue.main.async { + WebViewManager.shared.list.forEach { (key, webView) in + webView.navigationDelegate = nil + webView.stopLoading() + WebViewManager.shared.list[key] = nil + } + } + + newBookMarkList.forEach { (URLItem) in + loadWebView(URLItem.name, URLItem.url) + } + self.bookMarkList = newBookMarkList + } + + + func loadWebView(_ name: String, _ url: String) { + var url = url + if !url.hasPrefix("https://") && !url.hasPrefix("http://") { + url = "https://" + url + print(url) + } + if let loadURL = URL(string: url) { + DispatchQueue.main.async { + let wkWebView = WebView() + let request = URLRequest(url: loadURL) + + print(request) + WebViewManager.shared.list[name] = wkWebView + DispatchQueue.main.async { + wkWebView.load(request) + } + } + } + } +} diff --git a/Box42/Main/BoxBaseContainerViewController.swift b/Box42/Main/BoxBaseContainerViewController.swift index 4c1c4b0..abd8ce9 100644 --- a/Box42/Main/BoxBaseContainerViewController.swift +++ b/Box42/Main/BoxBaseContainerViewController.swift @@ -7,32 +7,18 @@ import Cocoa import SnapKit - -let bookMarkList = [ - ("home", "https://42box.kr/"), - ("23Coaltheme", "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"), - ("42STAT", "https://stat.42seoul.kr/home"), - ("24Hane", "https://24hoursarenotenough.42seoul.kr"), - ("80kCoding", "https://80000coding.oopy.io"), - ("where42", "https://www.where42.kr"), - ("cabi", "https://cabi.42seoul.io/"), - ("42gg", "https://42gg.kr/"), - ("textart", "https://textart.sh/"), -] +import Combine class BoxBaseContainerViewController: NSViewController { // MARK: - LeftContainer - // var splitView: BoxBaseSplitView = BoxBaseSplitView() + var splitView: BoxBaseSplitView = BoxBaseSplitView() var contentGroup: BoxContentsViewGroup = BoxContentsViewGroup() var toolbarGroupVC: ToolbarViewController = ToolbarViewController() var quickSlotGroupVC: QuickSlotViewController = QuickSlotViewController() var functionGroupVC: BoxFunctionViewController = BoxFunctionViewController() let windowViewGroupVC: WindowButtonViewController = WindowButtonViewController() - // var leftContainer: MovableContainerView = MovableContainerView() - // var buttonGroupVC: ButtonGroupViewController = ButtonGroupViewController() + var leftView: MovableContainerView = MovableContainerView() +// var buttonGroupVC: ButtonGroupViewController = ButtonGroupViewController() // MARK: - QuickSlot var preferenceVC: PreferencesViewController = PreferencesViewController() @@ -42,21 +28,12 @@ class BoxBaseContainerViewController: NSViewController { var quickSlotManagerVC: QuickSlotManagerViewController = QuickSlotManagerViewController() var quickSlotButtonCollectionVC: QuickSlotButtonCollectionViewController = QuickSlotButtonCollectionViewController() + + // MARK: - table View + var viewModel: BookmarkViewModel? = BookmarkViewModel.shared - // private let splitView: NSSplitView = { - // let splitView = NSSplitView() - // splitView.isVertical = true - // splitView.dividerStyle = .thick - // return splitView - // }() - - public let leftView: NSView = { - let view = NSView() - view.frame.size.width = 302 - 12 - view.frame.size.height = 1200 - return view - }() - + var cancellables: Set = [] + private let bookMarkView: NSView = { let view = NSView() return view @@ -68,9 +45,20 @@ class BoxBaseContainerViewController: NSViewController { tableView.headerView = nil return tableView }() + + + // MARK: - table View End - var buttonTitleArray = bookMarkList.map { $0.0 } - var urlArray = bookMarkList.map { $0.1 } + private func setupBindings() { + print("Setting up bindings...") // 디버깅 로그 + viewModel?.$bookMarkList.sink(receiveValue: { [weak self] newScripts in + print("Received new scripts: \(newScripts)") // 디버깅 로그 + DispatchQueue.main.async { + self?.tableView.reloadData() + } + }).store(in: &cancellables) + } + var selectedRow: Int? var selectedButton: DraggableButton? @@ -134,6 +122,7 @@ class BoxBaseContainerViewController: NSViewController { bookMarkView.snp.makeConstraints { make in make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) make.leading.trailing.equalToSuperview() + make.width.equalToSuperview() make.bottom.equalTo(quickSlotGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) } borderView.snp.makeConstraints { make in @@ -206,9 +195,7 @@ class BoxBaseContainerViewController: NSViewController { tableView.addTableColumn(column) - let scrollView = NSScrollView() - scrollView.hasVerticalScroller = true scrollView.documentView = tableView bookMarkView.addSubview(superView) @@ -229,6 +216,7 @@ class BoxBaseContainerViewController: NSViewController { scrollView.snp.makeConstraints { make in make.top.equalTo(superView.snp.bottom).offset(0) make.leading.trailing.equalToSuperview().offset(0) + make.width.equalToSuperview() make.bottom.equalToSuperview() } @@ -238,134 +226,113 @@ class BoxBaseContainerViewController: NSViewController { } @objc func addBookMarkButtonClicked(_ sender: NSButton) { - // splitView.removeArrangedSubview(contentGroup) - // contentGroup.removeFromSuperview() - // - // let newView = BookmarkEditorView(bookMarkList: bookMarkList) - // newView.wantsLayer = true - // newView.layer?.backgroundColor = NSColor.black.cgColor - // newView.layer?.cornerRadius = 20 - // newView.frame.size = contentGroup.frame.size - // - // contentGroup.addSubview(newView) - // newView.snp.makeConstraints { make in - // make.edges.equalToSuperview() - // } - // - // splitView.addArrangedSubview(contentGroup) + contentGroup.removeAllSubviews() + + let bookmarkTableView = BookmarkEditorTableView() + bookmarkTableView.setup() + bookmarkTableView.setupBindings() + + let scrollView = NSScrollView() + contentGroup.addSubview(scrollView) + scrollView.documentView = bookmarkTableView + + scrollView.snp.makeConstraints({ make in + make.edges.equalToSuperview() + }) + + bookmarkTableView.snp.makeConstraints({ make in + make.edges.equalToSuperview() + }) } override func viewDidLoad() { - // self.view.wantsLayer = true - // - //// self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor - // self.view.layer?.backgroundColor = NSColor(hex: "#E7E7E7").cgColor +// self.view.wantsLayer = true + super.viewDidLoad() + setupBindings() +// +//// self.view.layer?.backgroundColor = NSColor(hex: "#FF9548").cgColor +// self.view.layer?.backgroundColor = NSColor(hex: "#E7E7E7").cgColor NotificationCenter.default.addObserver(self, selector: #selector(handleButtonTapped), name: .collectionButtonTapped, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(headerTappedQuickSlotManagerHandle), name: .collectionHeaderTapped, object: nil) } - // func BoxButtonViewGroupInit() -> BoxButtonViewGroup { - // - // let buttonGroup = BoxButtonViewGroup { sender in - // self.clickBtn(sender: sender) - // } - // - // return buttonGroup - // } - - // func clickBtn(sender: Any?) { - // if let button = sender as? NSButton { - // guard let clickCount = NSApp.currentEvent?.clickCount else { return } - // if clickCount == 2 { - // WebViewManager.shared.list[button.title]!.reload() - // print("Dobule Click") - // } else if clickCount > 2 { - // if let currentURL = WebViewManager.shared.hostingWebView?.url { - // NSWorkspace.shared.open(currentURL) - // } - // print("Triple Click") - // } else if clickCount < 2 { - // contentGroup.removeAllSubviews() - // contentGroup.showWebviews(button) - // } - // } else { - // if let str = sender as? String { - // if str == "box" { - // contentGroup.removeAllSubviews() - // print("box inside") - // } - // } - // } - // } - // - // private func leftContainerInit() { - // leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width - // leftContainer.frame.size.height = BoxSizeManager.shared.windowButtonGroupSize.height - // leftContainer.addSubview(windowViewGroupVC.view) - // leftContainer.addSubview(buttonGroupVC.view) - // leftContainer.addSubview(toolbarGroupVC.view) - // leftContainer.addSubview(quickSlotGroupVC.view) - // leftContainer.addSubview(functionGroupVC.view) - // - // leftContainerAutolayout() - // } - // - // private func leftContainerAutolayout() { - // windowViewGroupVC.view.snp.makeConstraints { make in - // make.top.equalTo(leftContainer) - // make.left.equalTo(leftContainer).offset(3) - // make.width.equalTo(77) - // make.height.equalTo(21) - // } - // - // toolbarGroupVC.view.snp.makeConstraints { make in - // make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) - // make.right.equalTo(leftContainer) - // make.left.equalTo(leftContainer) - // make.height.equalTo(44 + 14 + 24) - // } - // - // buttonGroupVC.view.snp.makeConstraints { make in - // make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) - // make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) - // make.left.equalTo(leftContainer) - // make.bottom.equalTo(quickSlotGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) - // } - // - // quickSlotGroupVC.view.snp.makeConstraints { make in - // make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-27) - // make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) - // make.left.equalTo(leftContainer) - // make.height.equalTo(178) - // } - // - // functionGroupVC.view.snp.makeConstraints { make in - // make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) - // make.left.bottom.equalTo(leftContainer) - // } - // } - // - // func viewInit() { - // self.boxViewSizeInit() - // - // splitView.addArrangedSubview(leftContainer) - // splitView.addArrangedSubview(contentGroup) - // self.view.addSubview(splitView) - // - // splitView.snp.makeConstraints { make in - // make.top.equalToSuperview().offset(Constants.UI.groupAutolayout) - // make.left.equalToSuperview().offset(Constants.UI.groupAutolayout) - // make.right.equalToSuperview().offset(-Constants.UI.groupAutolayout) - // make.bottom.equalToSuperview().offset(-Constants.UI.groupAutolayout) - // } - // } - // - // func boxViewSizeInit() { - // self.view.frame.size.width = BoxSizeManager.shared.size.width - // self.view.frame.size.height = BoxSizeManager.shared.size.height - // } +// func BoxButtonViewGroupInit() -> BoxButtonViewGroup { +// +// let buttonGroup = BoxButtonViewGroup { sender in +// self.clickBtn(sender: sender) +// } +// +// return buttonGroup +// } +// +// private func leftContainerInit() { +// leftContainer.frame.size.width = BoxSizeManager.shared.windowButtonGroupSize.width +// leftContainer.frame.size.height = BoxSizeManager.shared.windowButtonGroupSize.height +// leftContainer.addSubview(windowViewGroupVC.view) +// leftContainer.addSubview(buttonGroupVC.view) +// leftContainer.addSubview(toolbarGroupVC.view) +// leftContainer.addSubview(quickSlotGroupVC.view) +// leftContainer.addSubview(functionGroupVC.view) +// +// leftContainerAutolayout() +// } +// +// private func leftContainerAutolayout() { +// windowViewGroupVC.view.snp.makeConstraints { make in +// make.top.equalTo(leftContainer) +// make.left.equalTo(leftContainer).offset(3) +// make.width.equalTo(77) +// make.height.equalTo(21) +// } +// +// toolbarGroupVC.view.snp.makeConstraints { make in +// make.top.equalTo(windowViewGroupVC.view.snp.bottom).offset(31) +// make.right.equalTo(leftContainer) +// make.left.equalTo(leftContainer) +// make.height.equalTo(44 + 14 + 24) +// } +// +// buttonGroupVC.view.snp.makeConstraints { make in +// make.top.equalTo(toolbarGroupVC.view.snp.bottom).offset(Constants.UI.groupAutolayout) +// make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) +// make.left.equalTo(leftContainer) +// make.bottom.equalTo(quickSlotGroupVC.view.snp.top).offset(-Constants.UI.groupAutolayout) +// } +// +// quickSlotGroupVC.view.snp.makeConstraints { make in +// make.bottom.equalTo(functionGroupVC.view.snp.top).offset(-27) +// make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) +// make.left.equalTo(leftContainer) +// make.height.equalTo(178) +// } +// +// functionGroupVC.view.snp.makeConstraints { make in +// make.right.equalTo(leftContainer).offset(-Constants.UI.groupAutolayout) +// make.left.bottom.equalTo(leftContainer) +// } +// } +// +// func viewInit() { +// self.boxViewSizeInit() +// +// splitView.addArrangedSubview(leftContainer) +// splitView.addArrangedSubview(contentGroup) +// self.view.addSubview(splitView) +// +// splitView.snp.makeConstraints { make in +// make.top.equalToSuperview().offset(Constants.UI.groupAutolayout) +// make.left.equalToSuperview().offset(Constants.UI.groupAutolayout) +// make.right.equalToSuperview().offset(-Constants.UI.groupAutolayout) +// make.bottom.equalToSuperview().offset(-Constants.UI.groupAutolayout) +// } +// } +// +// func boxViewSizeInit() { +// self.view.frame.size.width = BoxSizeManager.shared.size.width +// self.view.frame.size.height = BoxSizeManager.shared.size.height +// } } extension BoxBaseContainerViewController: NSSplitViewDelegate { @@ -381,25 +348,6 @@ extension BoxBaseContainerViewController: NSTableViewDelegate { pasteboardItem.setString(String(row), forType: .string) return pasteboardItem } - - func sendUpdatedDataToServer() { - let urlList = zip(buttonTitleArray, urlArray).map { ["name": $0.0, "url": $0.1] } - let jsonData = try? JSONSerialization.data(withJSONObject: ["urlList": urlList]) - - var request = URLRequest(url: URL(string:"https://api.42box.kr/user-service/users/me/url-list")!) - request.httpMethod = "POST" - request.httpBody = jsonData - - URLSession.shared.dataTask(with:request) { (data, response, error) in - if error != nil{ - print(error!.localizedDescription) - } - else{ - print("Data posted successfully") - } - }.resume() - } - } class ButtonTableCellView: NSTableCellView { @@ -415,7 +363,7 @@ class ButtonTableCellView: NSTableCellView { extension BoxBaseContainerViewController: NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { - return buttonTitleArray.count + return BookmarkViewModel.shared.bookMarkList.count } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { @@ -427,13 +375,15 @@ extension BoxBaseContainerViewController: NSTableViewDataSource { button.bezelStyle = .inline button.isBordered = false button.title = "" + button.associatedString = BookmarkViewModel.shared.bookMarkList[row].name button.registerForDraggedTypes([NSPasteboard.PasteboardType.string]) button.target = self button.action = #selector(buttonClicked(_:)) button.delegate = self let label = NSTextField(frame: NSRect(x: 26 + 21 + 8, y: 25 / 2, width: button.bounds.width, height: button.bounds.height)) - label.stringValue = buttonTitleArray[row] + + label.stringValue = BookmarkViewModel.shared.bookMarkList[row].name label.backgroundColor = .clear label.isBordered = false label.isEditable = false @@ -466,8 +416,7 @@ extension BoxBaseContainerViewController: NSTableViewDataSource { make.top.equalToSuperview().offset(2) make.leading.equalToSuperview() make.trailing.equalToSuperview() - make.width.equalTo(268) - // make.width.lessThanOrEqualTo(268) + make.width.equalToSuperview() make.height.equalTo(44) } @@ -492,10 +441,35 @@ extension BoxBaseContainerViewController: NSTableViewDataSource { selectedButton = sender sender.layer?.backgroundColor = NSColor.white.cgColor - if sender.tag < urlArray.count { - if let url = URL(string:urlArray[sender.tag]) { + if sender.tag < BookmarkViewModel.shared.bookMarkList.count { + if let url = URL(string: BookmarkViewModel.shared.bookMarkList[sender.tag].url) { print(url) - contentGroup.webView.load(URLRequest(url: url)) + clickBtn(sender: sender) + } + } + } + + func clickBtn(sender: Any?) { + if let button = sender as? NSButton { + guard let clickCount = NSApp.currentEvent?.clickCount else { return } + if clickCount == 2 { + WebViewManager.shared.list[button.title]?.reload() + print("Dobule Click") + } else if clickCount > 2 { + if let currentURL = WebViewManager.shared.hostingWebView?.url { + NSWorkspace.shared.open(currentURL) + } + print("Triple Click") + } else if clickCount < 2 { + contentGroup.removeAllSubviews() + contentGroup.showWebviews(button) // sender.tag + } + } else { + if let str = sender as? String { + if str == "box" { + contentGroup.removeAllSubviews() + print("box inside") + } } } } @@ -514,120 +488,21 @@ extension BoxBaseContainerViewController: NSTableViewDataSource { } let to = (from < row) ? row - 1 : row - let item = buttonTitleArray[from] - buttonTitleArray.remove(at: from) - buttonTitleArray.insert(item, at: to) - tableView.reloadData() + let item = BookmarkViewModel.shared.bookMarkList[from] + BookmarkViewModel.shared.bookMarkList.remove(at: from) + BookmarkViewModel.shared.bookMarkList.insert(item, at: to) for (_, subview) in tableView.subviews.enumerated() { guard let cellView = subview as? CustomTableCellView else { continue } - cellView.button.title = buttonTitleArray[cellView.rowIndex] + cellView.button.title = BookmarkViewModel.shared.bookMarkList[cellView.rowIndex].url } return true } } -class DraggableButton: NSButton, NSDraggingSource { - weak var delegate: BoxBaseContainerViewController? - var mouseDownEvent: NSEvent? - - func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation { - return .move - } - - override func mouseUp(with event: NSEvent) { - print("mouseUp") - if let down = self.mouseDownEvent { - if event.locationInWindow == down.locationInWindow { - self.target?.perform(self.action, with: self) - } - super.mouseUp(with:event) - self.mouseDownEvent = nil - } - } - - override func mouseDown(with event: NSEvent) { - print("mouseDown") - self.mouseDownEvent = event - if event.clickCount > 1 { - self.target?.perform(self.action, with: self) - } - } - - override func mouseDragged(with event: NSEvent) { - guard let down = self.mouseDownEvent else { return } - - let distance = hypot( - down.locationInWindow.x - event.locationInWindow.x, - down.locationInWindow.y - event.locationInWindow.y) - - if distance > 3 { // Adjust this as needed - let pasteboardItem = NSPasteboardItem() - pasteboardItem.setString("\(self.tag)", forType: .string) - - let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem) - - // Create a snapshot of the button - let snapshot = self.snapshot() - - // Set the dragging frame and contents - draggingItem.setDraggingFrame(self.bounds, contents:snapshot) - - beginDraggingSession(with: [draggingItem], event:self.mouseDownEvent!, source:self) - - self.mouseDownEvent = nil - } - } - - func snapshot() -> NSImage? { - guard let bitmapRep = bitmapImageRepForCachingDisplay(in: bounds) else { return nil } - cacheDisplay(in: bounds, to: bitmapRep) - let image = NSImage(size: bounds.size) - image.addRepresentation(bitmapRep) - return image - } - - override func viewDidMoveToWindow() { - super.viewDidMoveToWindow() - - let trackingArea = NSTrackingArea( - rect: bounds, - options: [.mouseEnteredAndExited, .activeAlways], - owner: self, - userInfo: nil - ) - - addTrackingArea(trackingArea) - } - - override func mouseEntered(with event: NSEvent) { - super.mouseEntered(with: event) - - if self != delegate?.selectedButton { - wantsLayer = true - layer?.frame.size = CGSize(width: 268.0, height: 44.0) - layer?.cornerRadius = 12 - layer?.backgroundColor = NSColor(red: 0.848, green: 0.848, blue: 0.848, alpha: 1).cgColor - } - } - - override func mouseExited(with event: NSEvent) { - super.mouseExited(with: event) - - if self != delegate?.selectedButton { - wantsLayer = true - layer?.frame.size = CGSize(width: 268.0, height: 44.0) - layer?.cornerRadius = 12 - layer?.backgroundColor = NSColor.clear.cgColor - } - } -} - - - //extension BoxBaseContainerViewController: BoxFunctionViewControllerDelegate { // func didTapBoxButton() { // clickBtn(sender: "box") diff --git a/Box42/Main/UI/MovableContainerView.swift b/Box42/Main/UI/MovableContainerView.swift index bd8dba6..88a5d15 100644 --- a/Box42/Main/UI/MovableContainerView.swift +++ b/Box42/Main/UI/MovableContainerView.swift @@ -10,6 +10,8 @@ import AppKit class MovableContainerView: NSView { init() { super.init(frame: .zero) + self.frame.size.width = 302 - 12 + self.frame.size.height = 1200 } required init?(coder: NSCoder) { diff --git a/Box42/Main/View/BookmarkEditorView.swift b/Box42/Main/View/BookmarkEditorView.swift deleted file mode 100644 index fc0088f..0000000 --- a/Box42/Main/View/BookmarkEditorView.swift +++ /dev/null @@ -1,104 +0,0 @@ -// -// BookmarkEditorView.swift -// Box42 -// -// Created by Dasol on 2023/09/04. -// - -import Cocoa - -class BookmarkRowView: NSView { - let nameField = NSTextField() - let urlField = NSTextField() - - init(bookmark: (String, String)) { - super.init(frame: .zero) - - nameField.stringValue = bookmark.0 - urlField.stringValue = bookmark.1 - - addSubview(nameField) - addSubview(urlField) - - nameField.snp.makeConstraints { make in - make.top.bottom.equalToSuperview() - make.leading.equalToSuperview() - make.width.equalToSuperview().multipliedBy(0.5) - } - - urlField.snp.makeConstraints { make in - make.top.bottom.trailing.equalToSuperview() - make.leading.equalTo(nameField.snp.trailing) - } - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -class BookmarkEditorView : NSView { - - var bookMarkList : [(String,String)] - var changeButton=NSButton(title:"Change",target:nil,action:nil) - var closeButton=NSButton(title:"Close",target:nil,action:nil) - - init(bookMarkList : [(String,String)]){ - - self.bookMarkList=bookMarkList - - super.init(frame:.zero) - - for (index, bookmark) in bookMarkList.enumerated(){ - let row=BookmarkRowView(bookmark: bookmark) - self.addSubview(row) - - row.snp.makeConstraints { make in - if index == 0 { - // First row should be at the top of the editor. - make.top.equalToSuperview() - } else { - // Other rows should be below the previous one. - make.top.equalTo(self.subviews[index - 1].snp.bottom) - } - - // All rows have the same height and span the entire width of the editor. - make.height.equalTo(44) // Or any other height you want. - make.left.right.equalToSuperview() - } - } - - self.addSubview(changeButton) - - changeButton.snp.makeConstraints {make in - if let lastSubview=self.subviews.last{ - // Place it under last subview - make.top.equalTo(lastSubview.snp.bottom).offset(10) - }else{ - make.top.equalToSuperview() - } - - make.centerX.equalToSuperview() - } - - self.addSubview(closeButton) - closeButton.target = self - closeButton.action = #selector(closeButtonClicked(_:)) - closeButton.snp.makeConstraints{maker in - maker.centerX.equalToSuperview() - maker.top.equalTo(changeButton.snp.bottom).offset(10) - maker.bottom.equalToSuperview().offset(-10) - } - } - - required init?(coder aDecoder:NSCoder){ - fatalError("init(coder:) has not been implemented") - } - - @objc func closeButtonClicked(_ sender:NSButton) { - removeFromSuperview() - } -} - - - diff --git a/Box42/Main/View/BoxContentsViewGroup.swift b/Box42/Main/View/BoxContentsViewGroup.swift index 0848b59..8c57685 100644 --- a/Box42/Main/View/BoxContentsViewGroup.swift +++ b/Box42/Main/View/BoxContentsViewGroup.swift @@ -9,109 +9,31 @@ import WebKit import SnapKit class BoxContentsViewGroup: NSView, WKUIDelegate { -// var webVC: WebViewController? + var webVC: WebViewController? var preferencesVC = PreferencesViewController() var scriptsVC = ScriptsViewController() - - var webView: WKWebView! - static let shared = BoxContentsViewGroup() + +// var webView: WKWebView! +// static let shared = BoxContentsViewGroup() init() { super.init(frame: .zero) -// webVC = WebViewController(nibName: nil, bundle: nil) + webVC = WebViewController(nibName: nil, bundle: nil) + self.wantsLayer = true self.layer?.cornerRadius = 20 self.layer?.masksToBounds = true -// self.addSubview(webVC!.view) -// webVC?.view.snp.makeConstraints { make in -// make.edges.equalTo(self) -// } - - let webConfiguration = WKWebViewConfiguration() - webView = WKWebView(frame: .zero, configuration: webConfiguration) - - webView.uiDelegate = self - WebViewManager.shared.hostingWebView = webView - self.addSubview(webView) - webView.snp.makeConstraints { make in + self.addSubview(webVC!.view) + webVC?.view.snp.makeConstraints { make in make.edges.equalTo(self) } - - if let url = URL(string: "https://www.42box.kr") { - let request = URLRequest(url: url) - webView.load(request) - } - - NotificationCenter.default.addObserver(self, selector: - #selector(goBack), name: - Notification.Name("goBack"), object:nil) - - NotificationCenter.default.addObserver(self, selector: - #selector(goForward), name: - Notification.Name("goForward"), object:nil) - - NotificationCenter.default.addObserver(self, selector: - #selector(reload), name: - Notification.Name("reload"), object:nil) - } - - deinit { - // view controller가 해제될 때 observer도 제거합니다. - NotificationCenter.default.removeObserver(self) - } - - @objc func goBack() { - if webView.canGoBack { - webView.goBack() - } - } - - @objc func goForward() { - if webView.canGoForward { - webView.goForward() - } - } - - @objc func reload() { - webView.reload() - } - - func webView(_ webView: WKWebView, - createWebViewWith configuration: WKWebViewConfiguration, - for navigationAction: WKNavigationAction, - windowFeatures: WKWindowFeatures) -> WKWebView? { - - if navigationAction.targetFrame == nil { - if let url = navigationAction.request.url { - if navigationAction.navigationType == .linkActivated { - webView.load(URLRequest(url: url)) - return nil - } - } - } - return nil } - func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) { - let openPanel = NSOpenPanel() - openPanel.canChooseFiles = true - openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection - openPanel.level = .popUpMenu - - openPanel.begin { (result) in - if result == .OK { - completionHandler(openPanel.urls) - } else { - completionHandler(nil) - } - } - } - required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func removeAllSubviews() { for subview in self.subviews { subview.removeFromSuperview() @@ -135,11 +57,11 @@ class BoxContentsViewGroup: NSView, WKUIDelegate { } func showWebviews(_ sender: NSButton) { - guard let currentWebview = WebViewManager.shared.list[sender.title] else { - print("No WebView found for title: \(sender.title)") + guard let currentWebview = WebViewManager.shared.list[sender.associatedString ?? "42Box"] else { + print("No WebView found for title: \(sender.associatedString)") return } - + WebViewManager.shared.hostingname = sender.title WebViewManager.shared.hostingWebView = currentWebview diff --git a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib index 0fda14b..a516887 100644 --- a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib +++ b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.xib @@ -1,8 +1,8 @@ - + - + diff --git a/Box42/QuickSlot/View/QuickSlotGroupView.swift b/Box42/QuickSlot/View/QuickSlotGroupView.swift index 785a196..6352cbd 100644 --- a/Box42/QuickSlot/View/QuickSlotGroupView.swift +++ b/Box42/QuickSlot/View/QuickSlotGroupView.swift @@ -9,9 +9,9 @@ import AppKit import SnapKit class QuickSlotGroupView: NSView { - -// lazy var divider: NSBox = Divider(completion: { [weak self] in self?.dividerAction?() }) - lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "Star"), completion: { [weak self] in self?.headerAction?() }) + + lazy var divider: NSBox = Divider(completion: { [weak self] in self?.dividerAction?() }) + lazy var headerView: QuickSlotHeaderView = QuickSlotHeaderView(image: NSImage(imageLiteralResourceName: "star"), completion: { [weak self] in self?.headerAction?() }) lazy var buttonCollectionView: QuickSlotButtonCollectionViewController = QuickSlotButtonCollectionViewController() var dividerAction: (() -> Void)? diff --git a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift index 351a562..c0daf9b 100644 --- a/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift +++ b/Box42/QuickSlot/ViewModel/QuickSlotViewModel.swift @@ -13,19 +13,19 @@ class QuickSlotViewModel { @Published var buttons: [QuickSlotButtonModel] = [] private init() { - let button1 = QuickSlotButtonModel(scriptUuid: UUID(uuidString: "37a56076-e72c-4efe-ba7f-de0effe7f4c3")!, + let button1 = QuickSlotButtonModel(scriptUuid: UUID(uuidString: "37a56076-e72c-4efe-ba7f-de0effe7f4c3f"), title: QuickSlotUI.title.clean, path: Bundle.main.path(forResource: "cleanCache", ofType: "sh"), type: "sh" ) let button2 = QuickSlotButtonModel(title: QuickSlotUI.title.preferences, - path: "preferences", + path: "default-preferences", type: "default-pref") let button3 = QuickSlotButtonModel(title: QuickSlotUI.title.scripts, - path: "scripts", + path: "default-scripts", type: "default-sh") let button4 = QuickSlotButtonModel(title: QuickSlotUI.title.user, - path: "user", + path: "default-user", type: "default-pref") buttons = [button1, button2, button3, button4] diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index bc8ce90..1f52499 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -32,6 +32,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { WebViewManager.shared.getCookie() API.getUserProfile(WebViewManager.shared.getCookieWebKit) _ = ScriptViewModel.shared + _ = BookmarkViewModel.shared } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/Box42/Scripts/View/Table/ScriptCellManager.swift b/Box42/Scripts/View/Table/ScriptCellManager.swift index 1dfc952..c3aa555 100644 --- a/Box42/Scripts/View/Table/ScriptCellManager.swift +++ b/Box42/Scripts/View/Table/ScriptCellManager.swift @@ -8,16 +8,14 @@ import AppKit import SnapKit -// MARK: - 다음 버전에 추가 예정 class ScriptCellManager: NSTableCellView { var nameLabel: NSTextField = NSTextField() var descriptionLabel: NSTextField = NSTextField() - var excuteButton: ScriptExcuteButton = ScriptExcuteButton() var deleteButton: ScriptDeleteButton = ScriptDeleteButton() var quickSlotButton: ScriptQuickSlotButton = ScriptQuickSlotButton() - var viewModel: ScriptViewModel? - var script: Script? + var viewModel: BookmarkViewModel? + var urlitem: URLItem? override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -32,13 +30,12 @@ class ScriptCellManager: NSTableCellView { addSubview(nameLabel) addSubview(descriptionLabel) addSubview(quickSlotButton) - addSubview(excuteButton) addSubview(deleteButton) nameLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.left.equalToSuperview().offset(16) - make.width.lessThanOrEqualTo(200).priority(.high) // 최대 너비와 우선순위 설정 + make.width.lessThanOrEqualTo(200).priority(.high) } deleteButton.snp.makeConstraints { make in @@ -48,16 +45,9 @@ class ScriptCellManager: NSTableCellView { make.height.equalTo(40) } - excuteButton.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.right.equalTo(deleteButton.snp.left).offset(-8) - make.width.equalTo(70) - make.height.equalTo(40) - } - quickSlotButton.snp.makeConstraints { make in make.centerY.equalToSuperview() - make.right.equalTo(excuteButton.snp.left).offset(-8) + make.right.equalTo(deleteButton.snp.left).offset(-8) make.width.equalTo(53) make.height.equalTo(40) } @@ -72,41 +62,50 @@ class ScriptCellManager: NSTableCellView { - func configure(with script: Script, viewModel: ScriptViewModel?) { - self.script = script + func configure(with urlitem: URLItem, viewModel: BookmarkViewModel?) { + self.urlitem = urlitem self.viewModel = viewModel - nameLabel.stringValue = script.name - descriptionLabel.stringValue = script.description ?? "description" + nameLabel.stringValue = urlitem.name + descriptionLabel.stringValue = urlitem.url deleteButton.target = self deleteButton.action = #selector(deleteButtonClicked) - excuteButton.target = self - excuteButton.action = #selector(excuteButtonClicked) - quickSlotButton.target = self quickSlotButton.action = #selector(quickSlotButtonclicked) } @objc func deleteButtonClicked() { - if let id = script?.scriptUuid { - viewModel?.deleteScript(id: id) - } +// if let id = script?.scriptUuid { +// viewModel?.deleteScript(id: id) +// } } @objc func excuteButtonClicked() { - // if let id = script?.scriptUuid { - // viewModel?.excuteScript(id: id) - // } - if let path = script?.path { - viewModel?.excuteScript(path: path) - } +// if let path = script?.path { +// viewModel?.excuteScript(path: path) +// } } @objc func quickSlotButtonclicked() { - if let id = script?.scriptUuid { - viewModel?.quickSlotScript(id: id) - } +// guard let path = script?.path else { +// return +// } +// +// let alreadyExists = QuickSlotViewModel.shared.buttons.contains { $0.path == path } +// +// if alreadyExists { +// QuickSlotViewModel.shared.removeButton(path) +// quickSlotButton.title = "퀵슬롯" +// } else { +// if QuickSlotViewModel.shared.buttons.count > 7 { +// return +// } else { +// quickSlotButton.title = "저장됨" +//// viewModel?.quickSlotScript(id: id) +// viewModel?.quickSlotScript(path: path) +// } +// } } } diff --git a/Box42/Scripts/View/Table/ScriptsTableView.swift b/Box42/Scripts/View/Table/ScriptsTableView.swift index b312a51..54a8d38 100644 --- a/Box42/Scripts/View/Table/ScriptsTableView.swift +++ b/Box42/Scripts/View/Table/ScriptsTableView.swift @@ -32,12 +32,6 @@ class ScriptsTableView: NSTableView { func setup() { self.delegate = self self.dataSource = self - - self.headerView = nil - self.selectionHighlightStyle = .none - - self.backgroundColor = .white - let column1 = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Scripts")) self.addTableColumn(column1) } diff --git a/Box42/Shared/API/GetUserProfile.swift b/Box42/Shared/API/GetUserProfile.swift index a631e2d..5188273 100644 --- a/Box42/Shared/API/GetUserProfile.swift +++ b/Box42/Shared/API/GetUserProfile.swift @@ -24,6 +24,7 @@ extension API { print(">> User MacOS Get :", userProfile) UserManager.shared.updateUserProfile(newProfile: userProfile) QuickSlotViewModel.shared.setUpQuickSlot() + BookmarkViewModel.shared.replaceBookMarkList(with: userProfile.urlList) case .failure(let error): print("Error: \(error)") } diff --git a/Box42/Shared/API/PutUserMeQuickSlot.swift b/Box42/Shared/API/PutUserMeQuickSlot.swift index f672f42..918561f 100644 --- a/Box42/Shared/API/PutUserMeQuickSlot.swift +++ b/Box42/Shared/API/PutUserMeQuickSlot.swift @@ -11,45 +11,40 @@ extension API { // MARK: - Scripts PUT: https://api.42box.kr/user-service/users/me/quick-slot // TODO: refactoring 필수 static func putUserMeQuickSlot(quickSlots: QuickSlotModels, completion: @escaping (Result) -> Void) { + WebViewManager.shared.storageSetCookie() - WebViewManager.shared.hostingWebView?.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in - let cookieStorage = HTTPCookieStorage.shared - for cookie in cookies { - cookieStorage.setCookie(cookie) - } - - let url = "https://api.42box.kr/user-service/users/me/quick-slot" - - var request = URLRequest(url: URL(string: url)!) - request.httpMethod = "PUT" - request.httpShouldHandleCookies = true - request.addValue("application/json", forHTTPHeaderField: "Content-Type") - - // Scripts 객체를 JSON 데이터로 인코딩 - print(quickSlots) - do { - let jsonData = try JSONEncoder().encode(quickSlots) - request.httpBody = jsonData - print(request.httpBody!) - } catch { - print("Failed to encode scripts: \(error)") + let url = "https://api.42box.kr/user-service/users/me/quick-slot" + + var request = URLRequest(url: URL(string: url)!) + request.httpMethod = "PUT" + request.httpShouldHandleCookies = true + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + + // Scripts 객체를 JSON 데이터로 인코딩 + print(quickSlots) + do { + let jsonData = try JSONEncoder().encode(quickSlots) + request.httpBody = jsonData + print(request.httpBody!) + } catch { + print("Failed to encode scripts: \(error)") + completion(.failure(error)) + return + } + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let error = error { completion(.failure(error)) return } - let task = URLSession.shared.dataTask(with: request) { (data, response, error) in - if let error = error { - completion(.failure(error)) - return - } - - if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 { - completion(.failure(NSError(domain: "InvalidStatusCode", code: httpResponse.statusCode, userInfo: nil))) - return - } - completion(.success(())) + if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 { + completion(.failure(NSError(domain: "InvalidStatusCode", code: httpResponse.statusCode, userInfo: nil))) + return } - task.resume() + completion(.success(())) } + task.resume() } } + diff --git a/Box42/Shared/API/PutUserMeUrlList.swift b/Box42/Shared/API/PutUserMeUrlList.swift new file mode 100644 index 0000000..695fe4a --- /dev/null +++ b/Box42/Shared/API/PutUserMeUrlList.swift @@ -0,0 +1,50 @@ +// +// PutUserMeUrlList.swift +// Box42 +// +// Created by Chanhee Kim on 9/5/23. +// + +import WebKit + +extension API { + // MARK: - Scripts PUT: https://api.42box.kr/user-service/users/me/url-list + // TODO: refactoring 필수 + static func putUserMeUrlList(urlList: URLList, completion: @escaping (Result) -> Void) { + + WebViewManager.shared.storageSetCookie() + + let url = "https://api.42box.kr/user-service/users/me/url-list" + + var request = URLRequest(url: URL(string: url)!) + request.httpMethod = "PUT" + request.httpShouldHandleCookies = true + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + + // Scripts 객체를 JSON 데이터로 인코딩 + print(urlList) + do { + let jsonData = try JSONEncoder().encode(urlList) + request.httpBody = jsonData + print(request.httpBody!) + } catch { + print("Failed to encode scripts: \(error)") + completion(.failure(error)) + return + } + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let error = error { + completion(.failure(error)) + return + } + + if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 { + completion(.failure(NSError(domain: "InvalidStatusCode", code: httpResponse.statusCode, userInfo: nil))) + return + } + completion(.success(())) + } + task.resume() + } +} diff --git a/Box42/Shared/User/UserProfile.swift b/Box42/Shared/User/UserProfile.swift index b786d4d..40c984d 100644 --- a/Box42/Shared/User/UserProfile.swift +++ b/Box42/Shared/User/UserProfile.swift @@ -19,11 +19,6 @@ struct UserProfile: Codable { let quickSlotList: [QuickSlotButtonModel] } -struct URLItem: Codable { - let name: String - let url: String -} - extension UserProfile { static func defaultProfile() -> UserProfile { return UserProfile( @@ -31,18 +26,7 @@ extension UserProfile { nickname: "fox", theme: 0, icon: "fox", - urlList: [URLItem(name: "home", url: "https://42box.kr/"), - URLItem(name: "23Coaltheme", url: "https://42box.github.io/front-end/"), - URLItem(name: "loopback", url: "http://127.0.0.1:3000/"), - URLItem(name: "Box 42", url: "https://42box.github.io/front-end/#/box"), - URLItem(name: "Intra 42", url: "https://intra.42.fr"), - URLItem(name: "Jiphyeonjeon", url: "https://42library.kr"), - URLItem(name: "42STAT", url: "https://stat.42seoul.kr/home"), - URLItem(name: "24Hane", url: "https://24hoursarenotenough.42seoul.kr"), - URLItem(name: "80kCoding", url: "https://80000coding.oopy.io"), - URLItem(name: "where42", url: "https://www.where42.kr"), - URLItem(name: "cabi", url: "https://cabi.42seoul.io/"), - URLItem(name: "42gg", url: "https://42gg.kr/")], + urlList: BookmarkViewModel.shared.bookMarkList, 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", diff --git a/Box42/Toolbar/Controller/ToolbarViewController.swift b/Box42/Toolbar/Controller/ToolbarViewController.swift index 50a77ae..3bcaf21 100644 --- a/Box42/Toolbar/Controller/ToolbarViewController.swift +++ b/Box42/Toolbar/Controller/ToolbarViewController.swift @@ -45,6 +45,8 @@ class ToolbarViewController: NSViewController { lazy var sidebarLeading: SideBarLeading = SideBarLeading(image: NSImage(imageLiteralResourceName: "toggle-on"), completion: { [weak self] in self?.sidebar() }) func sidebar() { +// print("sidebar") +// BookmarkViewModel.shared.addBookmark(item: URLItem(name: "chan", url: "https://42box.kr/")) toolbarViewGroup = BoxToolbarViewGroup() if let baseContainerVC = baseContainerVC { baseContainerVC.leftView.isHidden.toggle() diff --git a/Box42/WebView/Model/WebViewUI.swift b/Box42/WebView/Model/WebViewUI.swift index d5e4a63..fd5376c 100644 --- a/Box42/WebView/Model/WebViewUI.swift +++ b/Box42/WebView/Model/WebViewUI.swift @@ -14,5 +14,6 @@ enum WebViewUI { static let deleteScript = "deleteScript" static let icon = "icon" static let userProfile = "userProfile" + static let saveURL = "saveURL" } } diff --git a/Box42/WebView/WebView.swift b/Box42/WebView/WebView.swift index 9117d5d..2990542 100644 --- a/Box42/WebView/WebView.swift +++ b/Box42/WebView/WebView.swift @@ -26,6 +26,7 @@ class WebView: WKWebView, WKScriptMessageHandler, WKUIDelegate, WKNavigationDele 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.saveURL) self.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true self.configuration.preferences.javaScriptEnabled = true @@ -160,5 +161,25 @@ extension WebView { print("JSON decoding failed: \(error)") } } + + // URL 저장 + if message.name == WebViewUI.transfer.saveURL, let saveURL = message.body as? String { + let scriptJson = saveURL.data(using: .utf8) + print("saveURL : ", String(data: scriptJson!, encoding: .utf8) ?? "Invalid JSON data") + + do { + let decoder = JSONDecoder() + let saveURL = try decoder.decode(URLItem.self, from: scriptJson!) + + BookmarkViewModel.shared.addBookmarkByFront(item: URLItem(name: saveURL.name, url: saveURL.url)) + + print(saveURL) + + } catch { + print("JSON decoding failed: \(error)") + } + } + + } } diff --git a/Box42/WebView/WebViewController.swift b/Box42/WebView/WebViewController.swift index 3acc72d..8c7314c 100644 --- a/Box42/WebView/WebViewController.swift +++ b/Box42/WebView/WebViewController.swift @@ -10,6 +10,8 @@ import WebKit import Combine class WebViewController: NSViewController { + var viewModel = BookmarkViewModel.shared + var URLVM = WebViewModel() var webView: WKWebView! diff --git a/Box42/WebView/WebViewManager.swift b/Box42/WebView/WebViewManager.swift index 088c310..4d222ec 100644 --- a/Box42/WebView/WebViewManager.swift +++ b/Box42/WebView/WebViewManager.swift @@ -12,8 +12,6 @@ typealias WebViewMapping = [String : WKWebView] class WebViewManager: NSObject { static let shared = WebViewManager() - var icon = MenubarViewController() - var getCookieWebKit: WKWebView { didSet { getCookieWebKit.navigationDelegate = self @@ -45,6 +43,15 @@ class WebViewManager: NSObject { getCookieWebKit.load(request) } } + + func storageSetCookie() { + getCookieWebKit.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in + let cookieStorage = HTTPCookieStorage.shared + for cookie in cookies { + cookieStorage.setCookie(cookie) + } + } + } } extension WebViewManager: WKNavigationDelegate {