diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..e420e6d Binary files /dev/null and b/.DS_Store differ diff --git a/Downterm/Downterm.xcodeproj/project.pbxproj b/Downterm/Downterm.xcodeproj/project.pbxproj index 52acea9..90b7056 100644 --- a/Downterm/Downterm.xcodeproj/project.pbxproj +++ b/Downterm/Downterm.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0F4A88A33D93B6E100A1C001 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0F4A88A33D93B6E100A1C002 /* Assets.xcassets */; }; 2213F430F3D8A88033607CD2 /* NotchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA6359CF9DDF89413440300D /* NotchSettings.swift */; }; 247C6F84E7ADE7AED43381E2 /* DowntermApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B671125208055E5334CB85E /* DowntermApp.swift */; }; 26A767A10DDA77A690CC3C37 /* NotchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589421631401C819FE1A7BA9 /* NotchViewModel.swift */; }; @@ -35,6 +36,7 @@ 02FEFF9074A85F02C43D9408 /* NotchWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotchWindow.swift; sourceTree = ""; }; 0A973877BCE6084D0EBBBDBD /* SettingsWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsWindowController.swift; sourceTree = ""; }; 0B567F3B5D006D2B35630CFF /* LaunchAtLoginHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLoginHelper.swift; sourceTree = ""; }; + 0F4A88A33D93B6E100A1C002 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 15A290D4D21D6C01A583A372 /* ScreenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenManager.swift; sourceTree = ""; }; 1E47000112562615C7E59489 /* SwiftTermView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTermView.swift; sourceTree = ""; }; 1FC09C538CBE7C2D072008B2 /* NotchShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotchShape.swift; sourceTree = ""; }; @@ -72,6 +74,7 @@ 0EF94ED46B4860C241540F0A /* Resources */ = { isa = PBXGroup; children = ( + 0F4A88A33D93B6E100A1C002 /* Assets.xcassets */, 9547A79F60E46F4521A70674 /* Downterm.entitlements */, ); path = Resources; @@ -171,6 +174,7 @@ buildPhases = ( F3C6D5CD1247D246A3F6F7AB /* Sources */, 6085DF2BDFFB2A99C4ABD514 /* Frameworks */, + 0F4A88A33D93B6E100A1C003 /* Resources */, ); buildRules = ( ); @@ -214,6 +218,17 @@ }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + 0F4A88A33D93B6E100A1C003 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F4A88A33D93B6E100A1C001 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ F3C6D5CD1247D246A3F6F7AB /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -250,17 +265,20 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CLANG_USE_OPTIMIZATION_PROFILE = YES; CODE_SIGN_ENTITLEMENTS = Downterm/Resources/Downterm.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; COMBINE_HIDPI_IMAGES = YES; "DEVELOPMENT_TEAM[sdk=macosx*]" = G698BP272N; INFOPLIST_FILE = Downterm/Resources/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CommandNotch; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.downterm.app; + MARKETING_VERSION = 0.0.3; + PRODUCT_BUNDLE_IDENTIFIER = com.commandnotch.app; PRODUCT_NAME = Downterm; SDKROOT = macosx; }; @@ -334,17 +352,20 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CLANG_USE_OPTIMIZATION_PROFILE = YES; CODE_SIGN_ENTITLEMENTS = Downterm/Resources/Downterm.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; COMBINE_HIDPI_IMAGES = YES; "DEVELOPMENT_TEAM[sdk=macosx*]" = G698BP272N; INFOPLIST_FILE = Downterm/Resources/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CommandNotch; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.downterm.app; + MARKETING_VERSION = 0.0.3; + PRODUCT_BUNDLE_IDENTIFIER = com.commandnotch.app; PRODUCT_NAME = Downterm; SDKROOT = macosx; }; diff --git a/Downterm/Downterm.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate b/Downterm/Downterm.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate index de94b2f..00e0014 100644 Binary files a/Downterm/Downterm.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate and b/Downterm/Downterm.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Downterm/Downterm/Components/NotchShape.swift b/Downterm/Downterm/Components/NotchShape.swift index 71cb44e..a0aad11 100644 --- a/Downterm/Downterm/Components/NotchShape.swift +++ b/Downterm/Downterm/Components/NotchShape.swift @@ -5,13 +5,13 @@ import SwiftUI /// between the compact closed state and the expanded open state. /// /// The shape uses quadratic Bezier curves to produce the distinctive -/// "ear" ramps on each side when closed, and a clean rounded-bottom +/// top-edge cut-ins of the closed notch, and a clean rounded-bottom /// rectangle when open (topCornerRadius approaches 0). struct NotchShape: Shape { - /// Radius applied to the top-left and top-right outer corners (the "ears"). - /// When close to 0, the top corners become sharp and the shape is a - /// rectangle with rounded bottom corners — no visible ear ramps. + /// Radius applied to the top-left and top-right transitions where the notch + /// curves away from the screen edge. When close to 0, the top corners become + /// sharp and the shape is a rectangle with rounded bottom corners. var topCornerRadius: CGFloat /// Radius applied to the bottom-left and bottom-right inner corners. @@ -46,10 +46,10 @@ struct NotchShape: Shape { path.move(to: CGPoint(x: minX, y: minY)) if topR > 0.5 { - // Top-left ear: curve down from the top edge + // Leave the screen edge horizontally, then turn into the side wall. path.addQuadCurve( to: CGPoint(x: minX + topR, y: minY + topR), - control: CGPoint(x: minX, y: minY + topR) + control: CGPoint(x: minX + topR, y: minY) ) } else { path.addLine(to: CGPoint(x: minX, y: minY)) @@ -73,14 +73,14 @@ struct NotchShape: Shape { control: CGPoint(x: maxX - topR, y: maxY) ) - // Right edge up to top-right ear area + // Right edge up to the top-right transition path.addLine(to: CGPoint(x: maxX - topR, y: minY + topR)) if topR > 0.5 { - // Top-right ear: curve back up to the top edge + // Mirror the top-left transition. path.addQuadCurve( to: CGPoint(x: maxX, y: minY), - control: CGPoint(x: maxX, y: minY + topR) + control: CGPoint(x: maxX - topR, y: minY) ) } else { path.addLine(to: CGPoint(x: maxX, y: minY)) @@ -100,8 +100,8 @@ extension NotchShape { NotchShape(topCornerRadius: 6, bottomCornerRadius: 14) } - /// Open-state shape: no ear ramps, just rounded bottom corners. - /// topCornerRadius is near-zero so the ears disappear and the panel + /// Open-state shape: no top-edge cut-ins, just rounded bottom corners. + /// topCornerRadius is near-zero so the top becomes effectively flat and the panel /// extends flush to the top edge of the screen. static var opened: NotchShape { NotchShape(topCornerRadius: 0, bottomCornerRadius: 24) diff --git a/Downterm/Downterm/ContentView.swift b/Downterm/Downterm/ContentView.swift index 7eb79ae..507497e 100644 --- a/Downterm/Downterm/ContentView.swift +++ b/Downterm/Downterm/ContentView.swift @@ -65,6 +65,16 @@ struct ContentView: View { .animation(vm.notchState == .open ? vm.openAnimation : vm.closeAnimation, value: vm.notchSize.width) .animation(vm.notchState == .open ? vm.openAnimation : vm.closeAnimation, value: vm.notchSize.height) .onHover { handleHover($0) } + .onChange(of: vm.isCloseTransitionActive) { _, isClosing in + if isClosing { + hoverTask?.cancel() + } else { + scheduleHoverOpenIfNeeded() + } + } + .onDisappear { + hoverTask?.cancel() + } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .edgesIgnoringSafeArea(.all) } @@ -146,20 +156,30 @@ struct ContentView: View { private func handleHover(_ hovering: Bool) { if hovering { withAnimation(hoverAnimation) { vm.isHovering = true } - guard openNotchOnHover, vm.notchState == .closed else { return } - - hoverTask?.cancel() - hoverTask = Task { @MainActor in - try? await Task.sleep(nanoseconds: UInt64(minimumHoverDuration * 1_000_000_000)) - guard !Task.isCancelled, vm.isHovering else { return } - vm.requestOpen?() - } + scheduleHoverOpenIfNeeded() } else { hoverTask?.cancel() withAnimation(hoverAnimation) { vm.isHovering = false } } } + private func scheduleHoverOpenIfNeeded() { + hoverTask?.cancel() + guard openNotchOnHover, + vm.notchState == .closed, + !vm.isCloseTransitionActive, + vm.isHovering else { return } + + hoverTask = Task { @MainActor in + try? await Task.sleep(nanoseconds: UInt64(minimumHoverDuration * 1_000_000_000)) + guard !Task.isCancelled, + vm.isHovering, + vm.notchState == .closed, + !vm.isCloseTransitionActive else { return } + vm.requestOpen?() + } + } + private func abbreviate(_ title: String) -> String { title.count <= 30 ? title : String(title.prefix(28)) + "…" } diff --git a/Downterm/Downterm/Managers/PopoutWindowController.swift b/Downterm/Downterm/Managers/PopoutWindowController.swift index 71a280f..0ee6a36 100644 --- a/Downterm/Downterm/Managers/PopoutWindowController.swift +++ b/Downterm/Downterm/Managers/PopoutWindowController.swift @@ -1,6 +1,6 @@ import AppKit import SwiftUI -import SwiftTerm +import Combine /// Manages standalone pop-out terminal windows for detached tabs. /// Each detached tab gets its own resizable window with the terminal view. @@ -12,6 +12,7 @@ class PopoutWindowController: NSObject, NSWindowDelegate { /// Tracks open pop-out windows so they aren't released prematurely. private var windows: [UUID: NSWindow] = [:] private var sessions: [UUID: TerminalSession] = [:] + private var titleObservers: [UUID: AnyCancellable] = [:] private override init() { super.init() @@ -21,6 +22,12 @@ class PopoutWindowController: NSObject, NSWindowDelegate { func popout(session: TerminalSession) { let windowID = session.id + if let existingWindow = windows[windowID] { + existingWindow.makeKeyAndOrderFront(nil) + NSApp.activate(ignoringOtherApps: true) + return + } + let win = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 720, height: 480), styleMask: [.titled, .closable, .resizable, .miniaturizable], @@ -33,12 +40,14 @@ class PopoutWindowController: NSObject, NSWindowDelegate { win.delegate = self win.isReleasedWhenClosed = false - // Embed the terminal view directly - let tv = session.terminalView - tv.removeFromSuperview() - tv.frame = NSRect(origin: .zero, size: win.contentView!.bounds.size) - tv.autoresizingMask = [.width, .height] - win.contentView?.addSubview(tv) + let hostingView = NSHostingView( + rootView: SwiftTermView(session: session) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color.black) + .preferredColorScheme(.dark) + ) + hostingView.frame = NSRect(origin: .zero, size: win.contentRect(forFrameRect: win.frame).size) + win.contentView = hostingView win.center() win.makeKeyAndOrderFront(nil) @@ -48,16 +57,22 @@ class PopoutWindowController: NSObject, NSWindowDelegate { sessions[windowID] = session // Update window title when the terminal title changes - session.$title + titleObservers[windowID] = session.$title .receive(on: RunLoop.main) .sink { [weak win] title in win?.title = title } - .store(in: &popoutCancellables) } - private var popoutCancellables = Set() - // MARK: - NSWindowDelegate + func windowDidBecomeKey(_ notification: Notification) { + guard let window = notification.object as? NSWindow, + let entry = windows.first(where: { $0.value === window }), + let terminalView = sessions[entry.key]?.terminalView, + terminalView.window === window else { return } + + window.makeFirstResponder(terminalView) + } + func windowWillClose(_ notification: Notification) { guard let closingWindow = notification.object as? NSWindow else { return } @@ -66,8 +81,7 @@ class PopoutWindowController: NSObject, NSWindowDelegate { sessions[entry.key]?.terminate() sessions.removeValue(forKey: entry.key) windows.removeValue(forKey: entry.key) + titleObservers.removeValue(forKey: entry.key) } } } - -import Combine diff --git a/Downterm/Downterm/Managers/ScreenManager.swift b/Downterm/Downterm/Managers/ScreenManager.swift index 182863b..b40a477 100644 --- a/Downterm/Downterm/Managers/ScreenManager.swift +++ b/Downterm/Downterm/Managers/ScreenManager.swift @@ -10,6 +10,7 @@ import Combine class ScreenManager: ObservableObject { static let shared = ScreenManager() + private let focusRetryDelay: TimeInterval = 0.01 private(set) var windows: [String: NotchWindow] = [:] private(set) var viewModels: [String: NotchViewModel] = [:] @@ -91,6 +92,8 @@ class ScreenManager: ObservableObject { guard let vm = viewModels[screenUUID], let window = windows[screenUUID] else { return } + vm.cancelCloseTransition() + withAnimation(vm.openAnimation) { vm.open() } @@ -102,18 +105,15 @@ class ScreenManager: ObservableObject { NSApp.activate(ignoringOtherApps: true) window.makeKeyAndOrderFront(nil) - // After layout settles, push keyboard focus to the terminal view - DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { - if let tv = TerminalManager.shared.activeTab?.terminalView { - window.makeFirstResponder(tv) - } - } + focusActiveTerminal(in: screenUUID) } func closeNotch(screenUUID: String) { guard let vm = viewModels[screenUUID], let window = windows[screenUUID] else { return } + vm.beginCloseTransition() + withAnimation(vm.closeAnimation) { vm.close() } @@ -124,7 +124,9 @@ class ScreenManager: ObservableObject { private func detachActiveTab() { if let session = TerminalManager.shared.detachActiveTab() { - PopoutWindowController.shared.popout(session: session) + DispatchQueue.main.async { + PopoutWindowController.shared.popout(session: session) + } } } @@ -247,4 +249,20 @@ class ScreenManager: ObservableObject { repositionWindows() } } + + private func focusActiveTerminal(in screenUUID: String, attemptsRemaining: Int = 12) { + guard let window = windows[screenUUID], + let terminalView = TerminalManager.shared.activeTab?.terminalView else { return } + + if terminalView.window === window { + window.makeFirstResponder(terminalView) + return + } + + guard attemptsRemaining > 0 else { return } + + DispatchQueue.main.asyncAfter(deadline: .now() + focusRetryDelay) { [weak self] in + self?.focusActiveTerminal(in: screenUUID, attemptsRemaining: attemptsRemaining - 1) + } + } } diff --git a/Downterm/Downterm/Models/NotchViewModel.swift b/Downterm/Downterm/Models/NotchViewModel.swift index 621e822..6f52206 100644 --- a/Downterm/Downterm/Models/NotchViewModel.swift +++ b/Downterm/Downterm/Models/NotchViewModel.swift @@ -11,6 +11,7 @@ class NotchViewModel: ObservableObject { @Published var notchSize: CGSize @Published var closedNotchSize: CGSize @Published var isHovering: Bool = false + @Published var isCloseTransitionActive: Bool = false let terminalManager = TerminalManager.shared @@ -29,6 +30,8 @@ class NotchViewModel: ObservableObject { @AppStorage(NotchSettings.Keys.closeSpringResponse) private var closeSpringResponse = NotchSettings.Defaults.closeSpringResponse @AppStorage(NotchSettings.Keys.closeSpringDamping) private var closeSpringDamping = NotchSettings.Defaults.closeSpringDamping + private var closeTransitionTask: Task? + var openAnimation: Animation { .spring(response: openSpringResponse, dampingFraction: openSpringDamping) } @@ -63,4 +66,31 @@ class NotchViewModel: ObservableObject { var openNotchSize: CGSize { CGSize(width: openWidth, height: openHeight) } + + var closeInteractionLockDuration: TimeInterval { + max(closeSpringResponse + 0.2, 0.35) + } + + func beginCloseTransition() { + closeTransitionTask?.cancel() + isCloseTransitionActive = true + + let delay = closeInteractionLockDuration + closeTransitionTask = Task { @MainActor [weak self] in + try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) + guard let self, !Task.isCancelled else { return } + self.isCloseTransitionActive = false + self.closeTransitionTask = nil + } + } + + func cancelCloseTransition() { + closeTransitionTask?.cancel() + closeTransitionTask = nil + isCloseTransitionActive = false + } + + deinit { + closeTransitionTask?.cancel() + } } diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..64dc11e --- /dev/null +++ b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "icon_16x16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "icon_16x16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "icon_32x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "icon_32x32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "icon_128x128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "icon_128x128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "icon_256x256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "icon_256x256@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "icon_512x512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "icon_512x512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png new file mode 100644 index 0000000..ec0a5fa Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png new file mode 100644 index 0000000..f8aa415 Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png new file mode 100644 index 0000000..483a768 Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png new file mode 100644 index 0000000..64cb193 Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png new file mode 100644 index 0000000..f8aa415 Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png new file mode 100644 index 0000000..77de6ee Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png new file mode 100644 index 0000000..72e7deb Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png new file mode 100644 index 0000000..f31e0ff Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png new file mode 100644 index 0000000..77de6ee Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png new file mode 100644 index 0000000..bbf33c8 Binary files /dev/null and b/Downterm/Downterm/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/Downterm/Downterm/Resources/Assets.xcassets/Contents.json b/Downterm/Downterm/Resources/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Downterm/Downterm/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Downterm/Downterm/Resources/Info.plist b/Downterm/Downterm/Resources/Info.plist index 4710e06..f7eb611 100644 --- a/Downterm/Downterm/Resources/Info.plist +++ b/Downterm/Downterm/Resources/Info.plist @@ -5,15 +5,15 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - Downterm + CommandNotch CFBundleExecutable - Downterm + CommandNotch CFBundleIdentifier - com.downterm.app + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - Downterm + CommandNotch CFBundlePackageType APPL CFBundleShortVersionString diff --git a/icons/.DS_Store b/icons/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/icons/.DS_Store differ diff --git a/icons/Downterm-icon-128.png b/icons/Downterm-icon-128.png new file mode 100644 index 0000000..ec0a5fa Binary files /dev/null and b/icons/Downterm-icon-128.png differ diff --git a/icons/Downterm-icon-256.png b/icons/Downterm-icon-256.png new file mode 100644 index 0000000..f8aa415 Binary files /dev/null and b/icons/Downterm-icon-256.png differ diff --git a/icons/Downterm-icon-32.png b/icons/Downterm-icon-32.png new file mode 100644 index 0000000..64cb193 Binary files /dev/null and b/icons/Downterm-icon-32.png differ diff --git a/icons/Downterm-icon-512.png b/icons/Downterm-icon-512.png new file mode 100644 index 0000000..77de6ee Binary files /dev/null and b/icons/Downterm-icon-512.png differ diff --git a/icons/Downterm-icon-64.png b/icons/Downterm-icon-64.png new file mode 100644 index 0000000..f31e0ff Binary files /dev/null and b/icons/Downterm-icon-64.png differ diff --git a/icons/Icon.svg b/icons/Icon.svg new file mode 100644 index 0000000..4a13cb9 --- /dev/null +++ b/icons/Icon.svg @@ -0,0 +1,197 @@ + + + +