|
7 | 7 |
|
8 | 8 | import SwiftUI |
9 | 9 | import AppKit |
| 10 | +import Foundation |
10 | 11 |
|
11 | 12 | class WindowDelegate: NSObject, NSWindowDelegate { |
12 | 13 | func windowDidResize(_ notification: Notification) { |
@@ -56,62 +57,111 @@ class WindowDelegate: NSObject, NSWindowDelegate { |
56 | 57 | @main |
57 | 58 | struct DiscordApp: App { |
58 | 59 | @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate |
59 | | - @AppStorage("FakeNitro") var fakeNitro: Bool = false |
| 60 | + |
| 61 | + func extractMetadata(from plugin: String) -> ([String: String]) { |
| 62 | + var metadata = [String: String]() |
| 63 | + |
| 64 | + let lines = plugin.components(separatedBy: "\n") |
| 65 | + |
| 66 | + for line in lines { |
| 67 | + if line.contains ("==/VoxaPlugin==") { |
| 68 | + return metadata |
| 69 | + } |
| 70 | + |
| 71 | + if line.trimmingCharacters(in: .whitespaces).starts(with: "// @") { |
| 72 | + let cleanedLine = line.replacingOccurrences(of: "// @", with: "").trimmingCharacters(in: .whitespaces) |
| 73 | + if let separatorIndex = cleanedLine.firstIndex(of: ":") { |
| 74 | + let key = String(cleanedLine[..<separatorIndex]).trimmingCharacters(in: .whitespaces) |
| 75 | + let value = String(cleanedLine[cleanedLine.index(after: separatorIndex)...]).trimmingCharacters(in: .whitespaces) |
| 76 | + metadata[key] = value |
| 77 | + } |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + return metadata |
| 82 | + } |
| 83 | + |
| 84 | + init() { |
| 85 | + if let resourcePath = Bundle.main.resourcePath { |
| 86 | + let fileManager = FileManager.default |
| 87 | + |
| 88 | + do { |
| 89 | + let files = try fileManager.contentsOfDirectory(atPath: resourcePath) |
| 90 | + let possiblePluginFiles = files.filter { $0.hasSuffix(".js") } |
| 91 | + |
| 92 | + for file in possiblePluginFiles { |
| 93 | + // Build the full file path |
| 94 | + let filePath = (resourcePath as NSString).appendingPathComponent(file) |
| 95 | + |
| 96 | + // Check if it's a file (not a directory) |
| 97 | + var isDir: ObjCBool = false |
| 98 | + if fileManager.fileExists(atPath: filePath, isDirectory: &isDir), !isDir.boolValue { |
| 99 | + do { |
| 100 | + let script = try String(contentsOfFile: filePath, encoding: .utf8) |
| 101 | + var metadata = extractMetadata(from: script) |
| 102 | + let pathWithoutExtension = (file as NSString).deletingPathExtension |
| 103 | + let id = pathWithoutExtension.lowercased() |
| 104 | + |
| 105 | + metadata["pathWithoutExtension"] = pathWithoutExtension |
| 106 | + |
| 107 | + Vars.plugins[id] = metadata |
| 108 | + } catch { |
| 109 | + print("Couldn't load plugin \(filePath): \(error.localizedDescription)") |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + } catch { |
| 114 | + print("Error reading files from Bundle: \(error.localizedDescription)") |
| 115 | + } |
| 116 | + } else { |
| 117 | + print("Could not find the resource path in Bundle.main.") |
| 118 | + } |
| 119 | + } |
60 | 120 |
|
61 | 121 | var body: some Scene { |
62 | 122 | WindowGroup { |
63 | 123 | ContentView() |
64 | 124 | .onAppear { |
65 | 125 | // Use a guard to ensure there's a main screen |
66 | | - guard let mainScreen = NSScreen.main else { |
| 126 | + if (NSScreen.main == nil) { |
67 | 127 | print("No available main screen to set initial window frame.") |
68 | 128 | return |
69 | 129 | } |
70 | 130 |
|
71 | 131 | // If there's a main application window, configure it |
72 | 132 | if let window = NSApplication.shared.windows.first { |
73 | | - let screenFrame = mainScreen.visibleFrame |
74 | | - let newWidth: CGFloat = 1000 |
75 | | - let newHeight: CGFloat = 600 |
76 | | - |
77 | | - // Center the window |
78 | | - let centeredX = screenFrame.midX - (newWidth / 2) |
79 | | - let centeredY = screenFrame.midY - (newHeight / 2) |
80 | | - |
81 | | - let initialFrame = NSRect(x: centeredX, |
82 | | - y: centeredY, |
83 | | - width: newWidth, |
84 | | - height: newHeight) |
85 | | - |
86 | | - window.setFrame(initialFrame, display: true) |
87 | | - |
88 | | - // Configure window for resizing |
89 | | - window.styleMask.insert(.resizable) |
90 | | - |
91 | | - // Set min/max sizes |
92 | | - window.minSize = NSSize(width: 600, height: 400) |
93 | | - window.maxSize = NSSize(width: 2000, height: screenFrame.height) |
94 | | - |
95 | | - // Disable frame autosaving |
96 | | - window.setFrameAutosaveName("") |
97 | | - |
98 | | - // Assign delegate for traffic light positioning |
99 | | - window.delegate = appDelegate.windowDelegate |
| 133 | + // Get the visible frame of the main screen |
| 134 | + let screenFrame = NSScreen.main?.visibleFrame ?? .zero |
| 135 | + |
| 136 | + // Set the window frame to match the screen's visible frame |
| 137 | + window.setFrame(screenFrame, display: true) |
| 138 | + |
| 139 | + // Configure window for resizing |
| 140 | + window.styleMask.insert(.resizable) |
| 141 | + |
| 142 | + // Optionally, set min/max sizes if needed |
| 143 | + window.minSize = NSSize(width: 600, height: 400) |
| 144 | + |
| 145 | + // Disable frame autosaving |
| 146 | + window.setFrameAutosaveName("") |
| 147 | + |
| 148 | + // Assign delegate for traffic light positioning |
| 149 | + window.delegate = appDelegate.windowDelegate |
100 | 150 | } |
101 | 151 | } |
102 | 152 | } |
103 | 153 | .windowStyle(.hiddenTitleBar) |
104 | | - .commands { |
105 | | - CommandGroup(replacing: .windowArrangement) { } |
106 | | - |
107 | | - CommandMenu("Plugins") { |
108 | | - Button { |
109 | | - fakeNitro.toggle() |
110 | | - } label: { |
111 | | - Text("\(fakeNitro ? "Disable" : "Enable") Fake Nitro") |
112 | | - } |
113 | | - |
114 | | - } |
| 154 | + .commands { |
| 155 | + CommandGroup(replacing: .newItem) { |
| 156 | + Button("Reload") { |
| 157 | + hardReloadWebView(webView: Vars.webViewReference!) |
| 158 | + } |
| 159 | + .keyboardShortcut("r", modifiers: .command) |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + Settings { |
| 164 | + SettingsView() |
115 | 165 | } |
116 | 166 | } |
117 | 167 | } |
|
0 commit comments