From c655cc99173f5f63a144467ca89b5e01cfac7f8a Mon Sep 17 00:00:00 2001 From: h3p Date: Tue, 10 Mar 2026 16:14:21 +0100 Subject: [PATCH] Prepare v0.5.3 release updates and UI polish --- CHANGELOG.md | 19 ++ Neon Vision Editor.xcodeproj/project.pbxproj | 4 +- .../UI/ContentView+Toolbar.swift | 60 ++-- Neon Vision Editor/UI/ContentView.swift | 18 +- Neon Vision Editor/UI/NeonSettingsView.swift | 322 ++++++++++-------- Neon Vision Editor/UI/PanelsAndHelpers.swift | 10 +- Neon Vision Editor/UI/ThemeSettings.swift | 26 +- README.md | 14 +- 8 files changed, 298 insertions(+), 175 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be872e5..a5256eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to **Neon Vision Editor** are documented in this file. The format follows *Keep a Changelog*. Versions use semantic versioning with prerelease tags. +## [v0.5.3] - 2026-03-10 + +### Added +- Added a new high-readability colorful light theme preset: `Prism Daylight` (also selectable while app appearance is set to dark). +- Added double-click-to-close behavior for tabs on macOS tab strips. +- Added split editor settings sections (`Basics` / `Behavior`) to reduce scrolling in the Editor tab. + +### Improved +- Improved custom theme vibrancy by applying the vivid neon syntax profile to `Custom`, so syntax colors remain bright and saturated. +- Improved Cyber Lime readability in light mode by reducing overly bright green token intensity and switching to a blue cursor accent. +- Improved toolbar symbol color options on macOS with clearer separation between `Dark Gray` and `Black`, plus near-white rendering in dark mode for both options. +- Improved translucent macOS toolbar consistency by enforcing `0.8` opacity for toolbar surfaces in translucency mode. + +### Fixed +- Fixed toolbar-symbol contrast edge cases in dark mode where gray/black variants could appear too similar. + +### Release +- Notarized release published via `scripts/release_all.sh v0.5.3 notarized`. + ## [v0.5.2] - 2026-03-09 ### Added diff --git a/Neon Vision Editor.xcodeproj/project.pbxproj b/Neon Vision Editor.xcodeproj/project.pbxproj index a2da220..d404528 100644 --- a/Neon Vision Editor.xcodeproj/project.pbxproj +++ b/Neon Vision Editor.xcodeproj/project.pbxproj @@ -361,7 +361,7 @@ CODE_SIGNING_ALLOWED = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 489; + CURRENT_PROJECT_VERSION = 490; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = CS727NF72U; ENABLE_APP_SANDBOX = YES; @@ -444,7 +444,7 @@ CODE_SIGNING_ALLOWED = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 489; + CURRENT_PROJECT_VERSION = 490; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = CS727NF72U; ENABLE_APP_SANDBOX = YES; diff --git a/Neon Vision Editor/UI/ContentView+Toolbar.swift b/Neon Vision Editor/UI/ContentView+Toolbar.swift index 6384b69..045a5cd 100644 --- a/Neon Vision Editor/UI/ContentView+Toolbar.swift +++ b/Neon Vision Editor/UI/ContentView+Toolbar.swift @@ -39,6 +39,24 @@ extension ContentView { "AI Provider for Code Completion" } +#if os(macOS) + private var macToolbarSymbolColor: Color { + let isDarkMode = colorScheme == .dark + switch toolbarSymbolsColorMacRaw { + case "black": + return isDarkMode + ? Color(.sRGB, white: 0.94, opacity: 1.0) + : .black + case "darkGray": + return isDarkMode + ? Color(.sRGB, white: 0.84, opacity: 1.0) + : Color(.sRGB, white: 0.40, opacity: 1.0) + default: + return NeonUIStyle.accentBlue + } + } +#endif + #if os(iOS) private var iOSToolbarChromeStyle: GlassChromeStyle { .single } private var iOSToolbarTintColor: Color { @@ -941,19 +959,19 @@ extension ContentView { ToolbarItemGroup(placement: .primaryAction) { Button(action: { openFileFromToolbar() }) { Label("Open", systemImage: "folder") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Open File… (Cmd+O)") Button(action: { viewModel.addNewTab() }) { Label("New Tab", systemImage: "plus.square.on.square") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("New Tab (Cmd+T)") Button(action: { requestCloseAllTabsFromToolbar() }) { Label("Close All Tabs", systemImage: "xmark.square") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Close All Tabs") @@ -961,7 +979,7 @@ extension ContentView { saveCurrentTabFromToolbar() }) { Label("Save", systemImage: "square.and.arrow.down") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .disabled(viewModel.selectedTab == nil) .help("Save File (Cmd+S)") @@ -970,7 +988,7 @@ extension ContentView { showFindReplace = true }) { Label("Find", systemImage: "magnifyingglass") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Find & Replace (Cmd+F)") @@ -978,7 +996,7 @@ extension ContentView { openSettings() }) { Label("Settings", systemImage: "gearshape") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Settings") } @@ -1036,7 +1054,7 @@ extension ContentView { toggleMarkdownPreviewFromToolbar() }) { Label("Markdown Preview", systemImage: showMarkdownPreviewPane ? "doc.richtext.fill" : "doc.richtext") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .disabled(currentLanguage != "markdown") .help("Toggle Markdown Preview") @@ -1049,7 +1067,7 @@ extension ContentView { Button("Compact") { markdownPreviewTemplateRaw = "compact" } } label: { Label("Preview Style", systemImage: "textformat.size") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Markdown Preview Template") } @@ -1058,7 +1076,7 @@ extension ContentView { Button(action: { undoFromToolbar() }) { Label("Undo", systemImage: "arrow.uturn.backward") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Undo (Cmd+Z)") .keyboardShortcut("z", modifiers: .command) @@ -1068,7 +1086,7 @@ extension ContentView { showUpdaterDialog(checkNow: true) }) { Label("Updates", systemImage: "arrow.triangle.2.circlepath.circle") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Check for Updates") } @@ -1078,20 +1096,20 @@ extension ContentView { openWindow(id: "blank-window") }) { Label("New Window", systemImage: "macwindow.badge.plus") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("New Window (Cmd+N)") #endif Button(action: { adjustEditorFontSize(-1) }) { Label("Font -", systemImage: "textformat.size.smaller") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Decrease Font Size") Button(action: { adjustEditorFontSize(1) }) { Label("Font +", systemImage: "textformat.size.larger") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Increase Font Size") @@ -1099,7 +1117,7 @@ extension ContentView { requestClearEditorContent() }) { Label("Clear", systemImage: "eraser") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Clear Editor") @@ -1107,7 +1125,7 @@ extension ContentView { insertTemplateForCurrentLanguage() }) { Label("Template", systemImage: "doc.badge.plus") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Insert Template for Current Language") @@ -1115,7 +1133,7 @@ extension ContentView { toggleSidebarFromToolbar() }) { Label("Sidebar", systemImage: "sidebar.left") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) .symbolVariant(viewModel.showSidebar ? .fill : .none) } .help("Toggle Sidebar (Cmd+Opt+S)") @@ -1124,7 +1142,7 @@ extension ContentView { toggleProjectSidebarFromToolbar() }) { Label("Project", systemImage: "sidebar.right") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) .symbolVariant(showProjectStructureSidebar ? .fill : .none) } .help("Toggle Project Structure Sidebar") @@ -1133,7 +1151,7 @@ extension ContentView { toggleAutoCompletion() }) { Label("AI", systemImage: "bolt.horizontal.circle") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) .symbolVariant(isAutoCompletionEnabled ? .fill : .none) } .help(isAutoCompletionEnabled ? "Disable Code Completion" : "Enable Code Completion") @@ -1143,7 +1161,7 @@ extension ContentView { showBracketHelperBarMac.toggle() }) { Label("Brackets", systemImage: "chevron.left.chevron.right") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) .symbolVariant(showBracketHelperBarMac ? .fill : .none) } .help(showBracketHelperBarMac ? "Hide Bracket Helper Bar" : "Show Bracket Helper Bar") @@ -1154,7 +1172,7 @@ extension ContentView { UserDefaults.standard.set(viewModel.isBrainDumpMode, forKey: "BrainDumpModeEnabled") }) { Label("Brain Dump", systemImage: "note.text") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) .symbolVariant(viewModel.isBrainDumpMode ? .fill : .none) } .help("Brain Dump Mode") @@ -1166,7 +1184,7 @@ extension ContentView { NotificationCenter.default.post(name: .toggleTranslucencyRequested, object: enableTranslucentWindow) }) { Label("Translucency", systemImage: enableTranslucentWindow ? "rectangle.fill" : "rectangle") - .foregroundStyle(NeonUIStyle.accentBlue) + .foregroundStyle(macToolbarSymbolColor) } .help("Toggle Translucent Window Background") .accessibilityLabel("Translucent Window Background") diff --git a/Neon Vision Editor/UI/ContentView.swift b/Neon Vision Editor/UI/ContentView.swift index 46e4e01..07a61b7 100644 --- a/Neon Vision Editor/UI/ContentView.swift +++ b/Neon Vision Editor/UI/ContentView.swift @@ -331,6 +331,7 @@ struct ContentView: View { #if os(macOS) @State private var hostWindowNumber: Int? = nil @AppStorage("ShowBracketHelperBarMac") var showBracketHelperBarMac: Bool = false + @AppStorage("SettingsToolbarSymbolsColorMac") var toolbarSymbolsColorMacRaw: String = "blue" @State private var windowCloseConfirmationDelegate: WindowCloseConfirmationDelegate? = nil #endif @State var showMarkdownPreviewPane: Bool = false @@ -433,6 +434,13 @@ struct ContentView: View { } return AnyShapeStyle(Color(nsColor: .textBackgroundColor)) } + + private var macToolbarBackgroundStyle: AnyShapeStyle { + if enableTranslucentWindow { + return AnyShapeStyle(macTranslucencyMode.material.opacity(0.8)) + } + return AnyShapeStyle(Color(nsColor: .textBackgroundColor)) + } #elseif os(iOS) var primaryGlassMaterial: Material { colorScheme == .dark ? .regularMaterial : .ultraThinMaterial } var toolbarFallbackColor: Color { @@ -4066,7 +4074,7 @@ struct ContentView: View { } #if os(macOS) .toolbarBackground( - macChromeBackgroundStyle, + macToolbarBackgroundStyle, for: ToolbarPlacement.windowToolbar ) .toolbarBackgroundVisibility(Visibility.visible, for: ToolbarPlacement.windowToolbar) @@ -4695,6 +4703,12 @@ struct ContentView: View { .padding(.vertical, 6) } .buttonStyle(.plain) +#if os(macOS) + .simultaneousGesture( + TapGesture(count: 2) + .onEnded { requestCloseTab(tab) } + ) +#endif Button { requestCloseTab(tab) @@ -4722,7 +4736,7 @@ struct ContentView: View { } .frame(minHeight: 42, maxHeight: 42, alignment: .center) #if os(macOS) - .background(macChromeBackgroundStyle) + .background(macToolbarBackgroundStyle) #else .background( enableTranslucentWindow diff --git a/Neon Vision Editor/UI/NeonSettingsView.swift b/Neon Vision Editor/UI/NeonSettingsView.swift index 21b4850..ccee896 100644 --- a/Neon Vision Editor/UI/NeonSettingsView.swift +++ b/Neon Vision Editor/UI/NeonSettingsView.swift @@ -29,6 +29,7 @@ struct NeonSettingsView: View { @AppStorage("SettingsEditorFontSize") private var editorFontSize: Double = 14 @AppStorage("SettingsLineHeight") private var lineHeight: Double = 1.0 @AppStorage("SettingsAppearance") private var appearance: String = "system" + @AppStorage("SettingsToolbarSymbolsColorMac") private var toolbarSymbolsColorMacRaw: String = "blue" #if os(iOS) @AppStorage("EnableTranslucentWindow") private var translucentWindow: Bool = true #else @@ -73,6 +74,7 @@ struct NeonSettingsView: View { @State private var showDataDisclosureDialog: Bool = false @State private var availableEditorFonts: [String] = [] @State private var moreSectionTab: String = "support" + @State private var editorSectionTab: String = "basics" @State private var diagnosticsCopyStatus: String = "" @State private var supportRefreshTask: Task? @State private var isDiscoveringFonts: Bool = false @@ -271,7 +273,8 @@ struct NeonSettingsView: View { minSize: macSettingsWindowSize.min, idealSize: macSettingsWindowSize.ideal, translucentEnabled: supportsTranslucency && translucentWindow, - translucencyModeRaw: macTranslucencyModeRaw + translucencyModeRaw: macTranslucencyModeRaw, + appearanceRaw: appearance ) ) #endif @@ -512,6 +515,17 @@ struct NeonSettingsView: View { .pickerStyle(.segmented) } + HStack(alignment: .center, spacing: UI.space12) { + Text("Toolbar Symbols") + .frame(width: isCompactSettingsLayout ? nil : standardLabelWidth, alignment: .leading) + Picker("", selection: $toolbarSymbolsColorMacRaw) { + Text("Blue").tag("blue") + Text("Dark Gray").tag("darkGray") + Text("Black").tag("black") + } + .pickerStyle(.segmented) + } + if supportsTranslucency { Toggle("Translucent Window", isOn: $translucentWindow) .frame(maxWidth: .infinity, alignment: .leading) @@ -961,13 +975,88 @@ struct NeonSettingsView: View { title: "Editor", subtitle: "Display, indentation, editing behavior, and completion sources." ) + editorSectionPicker + if editorSectionTab == "basics" { + editorBasicsSettings + } else { + editorBehaviorSettings + } + } + } + + private var editorSectionPicker: some View { + VStack(alignment: .leading, spacing: UI.space8) { + Text("Section") + .font(Typography.footnote) + .foregroundStyle(.secondary) + Picker("Section", selection: $editorSectionTab) { + Text("Basics").tag("basics") + Text("Behavior").tag("behavior") + } + .pickerStyle(.segmented) + } + .frame(maxWidth: .infinity, alignment: .leading) + } + + private var editorBasicsSettings: some View { #if os(iOS) - VStack(spacing: UI.space16) { - settingsCardSection( - title: "Display", - icon: "eye", - tip: "Scope visuals are best used with line wrap disabled." - ) { + VStack(spacing: UI.space16) { + settingsCardSection( + title: "Display", + icon: "eye", + tip: "Scope visuals are best used with line wrap disabled." + ) { + Toggle("Show Line Numbers", isOn: $showLineNumbers) + Toggle("Highlight Current Line", isOn: $highlightCurrentLine) + Toggle("Highlight Matching Brackets", isOn: $highlightMatchingBrackets) + Toggle("Show Scope Guides (Non-Swift)", isOn: $showScopeGuides) + Toggle("Highlight Scoped Region", isOn: $highlightScopeBackground) + Toggle("Line Wrap", isOn: $lineWrapEnabled) + Text("When Line Wrap is enabled, scope guides/scoped region are turned off to avoid layout conflicts.") + .font(Typography.footnote) + .foregroundStyle(.secondary) + Text("Scope guides are intended for non-Swift languages. Swift favors matching-token highlight.") + .font(Typography.footnote) + .foregroundStyle(.secondary) + Text("Invisible character markers are disabled to avoid whitespace glyph artifacts.") + .font(Typography.footnote) + .foregroundStyle(.secondary) + } + + settingsCardSection( + title: "Indentation", + icon: "increase.indent", + emphasis: .secondary + ) { + Picker("Indent Style", selection: $indentStyle) { + Text("Spaces").tag("spaces") + Text("Tabs").tag("tabs") + } + .pickerStyle(.segmented) + + Stepper(value: $indentWidth, in: 2...8, step: 1) { + Text(localized("Indent Width: %lld", Int64(indentWidth))) + } + } + + settingsCardSection( + title: "Layout", + icon: "sidebar.left", + emphasis: .secondary + ) { + Picker("Project Navigator Position", selection: $projectNavigatorPlacementRaw) { + Text("Left").tag(ContentView.ProjectNavigatorPlacement.leading.rawValue) + Text("Right").tag(ContentView.ProjectNavigatorPlacement.trailing.rawValue) + } + .pickerStyle(.segmented) + } + } +#else + GroupBox("Editor Basics") { + VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading, spacing: UI.space10) { + Text("Display") + .font(Typography.sectionHeadline) Toggle("Show Line Numbers", isOn: $showLineNumbers) Toggle("Highlight Current Line", isOn: $highlightCurrentLine) Toggle("Highlight Matching Brackets", isOn: $highlightMatchingBrackets) @@ -984,12 +1073,13 @@ struct NeonSettingsView: View { .font(Typography.footnote) .foregroundStyle(.secondary) } + .frame(maxWidth: .infinity, alignment: .leading) - settingsCardSection( - title: "Indentation", - icon: "increase.indent", - emphasis: .secondary - ) { + Divider() + + VStack(alignment: .leading, spacing: UI.space10) { + Text("Indentation") + .font(Typography.sectionHeadline) Picker("Indent Style", selection: $indentStyle) { Text("Spaces").tag("spaces") Text("Tabs").tag("tabs") @@ -1000,24 +1090,76 @@ struct NeonSettingsView: View { Text(localized("Indent Width: %lld", Int64(indentWidth))) } } + .frame(maxWidth: .infinity, alignment: .leading) - settingsCardSection( - title: "Layout", - icon: "sidebar.left", - emphasis: .secondary - ) { + Divider() + + VStack(alignment: .leading, spacing: UI.space10) { + Text("Layout") + .font(Typography.sectionHeadline) Picker("Project Navigator Position", selection: $projectNavigatorPlacementRaw) { Text("Left").tag(ContentView.ProjectNavigatorPlacement.leading.rawValue) Text("Right").tag(ContentView.ProjectNavigatorPlacement.trailing.rawValue) } .pickerStyle(.segmented) } + .frame(maxWidth: .infinity, alignment: .leading) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(UI.groupPadding) + } +#endif + } - settingsCardSection( - title: "Performance", - icon: "speedometer", - emphasis: .secondary - ) { + private var editorBehaviorSettings: some View { +#if os(iOS) + VStack(spacing: UI.space16) { + settingsCardSection( + title: "Performance", + icon: "speedometer", + emphasis: .secondary + ) { + Picker("Preset", selection: $performancePresetRaw) { + Text("Balanced").tag(ContentView.PerformancePreset.balanced.rawValue) + Text("Large Files").tag(ContentView.PerformancePreset.largeFiles.rawValue) + Text("Battery").tag(ContentView.PerformancePreset.battery.rawValue) + } + .pickerStyle(.segmented) + Text("Balanced keeps default behavior. Large Files and Battery enter performance mode earlier.") + .font(Typography.footnote) + .foregroundStyle(.secondary) + } + + settingsCardSection( + title: "Editing", + icon: "keyboard", + emphasis: .secondary + ) { + Toggle("Auto Indent", isOn: $autoIndent) + Toggle("Auto Close Brackets", isOn: $autoCloseBrackets) + Toggle("Trim Trailing Whitespace", isOn: $trimTrailingWhitespace) + Toggle("Trim Edges for Syntax Detection", isOn: $trimWhitespaceForSyntaxDetection) + } + + settingsCardSection( + title: "Completion", + icon: "sparkles", + emphasis: .secondary + ) { + Toggle("Enable Completion", isOn: $completionEnabled) + Toggle("Include Words in Document", isOn: $completionFromDocument) + Toggle("Include Syntax Keywords", isOn: $completionFromSyntax) + Text("For lower latency on large files, keep only one completion source enabled.") + .font(Typography.footnote) + .foregroundStyle(.secondary) + } + } +#else + GroupBox("Editor Behavior") { + VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading, spacing: UI.space10) { + Text("Performance") + .font(Typography.sectionHeadline) Picker("Preset", selection: $performancePresetRaw) { Text("Balanced").tag(ContentView.PerformancePreset.balanced.rawValue) Text("Large Files").tag(ContentView.PerformancePreset.largeFiles.rawValue) @@ -1028,23 +1170,25 @@ struct NeonSettingsView: View { .font(Typography.footnote) .foregroundStyle(.secondary) } + .frame(maxWidth: .infinity, alignment: .leading) - settingsCardSection( - title: "Editing", - icon: "keyboard", - emphasis: .secondary - ) { + Divider() + + VStack(alignment: .leading, spacing: UI.space10) { + Text("Editing") + .font(Typography.sectionHeadline) Toggle("Auto Indent", isOn: $autoIndent) Toggle("Auto Close Brackets", isOn: $autoCloseBrackets) Toggle("Trim Trailing Whitespace", isOn: $trimTrailingWhitespace) Toggle("Trim Edges for Syntax Detection", isOn: $trimWhitespaceForSyntaxDetection) } + .frame(maxWidth: .infinity, alignment: .leading) - settingsCardSection( - title: "Completion", - icon: "sparkles", - emphasis: .secondary - ) { + Divider() + + VStack(alignment: .leading, spacing: UI.space10) { + Text("Completion") + .font(Typography.sectionHeadline) Toggle("Enable Completion", isOn: $completionEnabled) Toggle("Include Words in Document", isOn: $completionFromDocument) Toggle("Include Syntax Keywords", isOn: $completionFromSyntax) @@ -1052,109 +1196,12 @@ struct NeonSettingsView: View { .font(Typography.footnote) .foregroundStyle(.secondary) } - } -#else - GroupBox("Editor") { - VStack(alignment: .leading, spacing: 16) { - VStack(alignment: .leading, spacing: UI.space10) { - Text("Display") - .font(Typography.sectionHeadline) - Toggle("Show Line Numbers", isOn: $showLineNumbers) - Toggle("Highlight Current Line", isOn: $highlightCurrentLine) - Toggle("Highlight Matching Brackets", isOn: $highlightMatchingBrackets) - Toggle("Show Scope Guides (Non-Swift)", isOn: $showScopeGuides) - Toggle("Highlight Scoped Region", isOn: $highlightScopeBackground) - Toggle("Line Wrap", isOn: $lineWrapEnabled) - Text("When Line Wrap is enabled, scope guides/scoped region are turned off to avoid layout conflicts.") - .font(Typography.footnote) - .foregroundStyle(.secondary) - Text("Scope guides are intended for non-Swift languages. Swift favors matching-token highlight.") - .font(Typography.footnote) - .foregroundStyle(.secondary) - Text("Invisible character markers are disabled to avoid whitespace glyph artifacts.") - .font(Typography.footnote) - .foregroundStyle(.secondary) - } - .frame(maxWidth: .infinity, alignment: .leading) - - Divider() - - VStack(alignment: .leading, spacing: UI.space10) { - Text("Indentation") - .font(Typography.sectionHeadline) - Picker("Indent Style", selection: $indentStyle) { - Text("Spaces").tag("spaces") - Text("Tabs").tag("tabs") - } - .pickerStyle(.segmented) - - Stepper(value: $indentWidth, in: 2...8, step: 1) { - Text(localized("Indent Width: %lld", Int64(indentWidth))) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - - Divider() - - VStack(alignment: .leading, spacing: UI.space10) { - Text("Layout") - .font(Typography.sectionHeadline) - Picker("Project Navigator Position", selection: $projectNavigatorPlacementRaw) { - Text("Left").tag(ContentView.ProjectNavigatorPlacement.leading.rawValue) - Text("Right").tag(ContentView.ProjectNavigatorPlacement.trailing.rawValue) - } - .pickerStyle(.segmented) - } - .frame(maxWidth: .infinity, alignment: .leading) - - Divider() - - VStack(alignment: .leading, spacing: UI.space10) { - Text("Performance") - .font(Typography.sectionHeadline) - Picker("Preset", selection: $performancePresetRaw) { - Text("Balanced").tag(ContentView.PerformancePreset.balanced.rawValue) - Text("Large Files").tag(ContentView.PerformancePreset.largeFiles.rawValue) - Text("Battery").tag(ContentView.PerformancePreset.battery.rawValue) - } - .pickerStyle(.segmented) - Text("Balanced keeps default behavior. Large Files and Battery enter performance mode earlier.") - .font(Typography.footnote) - .foregroundStyle(.secondary) - } - .frame(maxWidth: .infinity, alignment: .leading) - - Divider() - - VStack(alignment: .leading, spacing: UI.space10) { - Text("Editing") - .font(Typography.sectionHeadline) - Toggle("Auto Indent", isOn: $autoIndent) - Toggle("Auto Close Brackets", isOn: $autoCloseBrackets) - Toggle("Trim Trailing Whitespace", isOn: $trimTrailingWhitespace) - Toggle("Trim Edges for Syntax Detection", isOn: $trimWhitespaceForSyntaxDetection) - } - .frame(maxWidth: .infinity, alignment: .leading) - - Divider() - - VStack(alignment: .leading, spacing: UI.space10) { - Text("Completion") - .font(Typography.sectionHeadline) - Toggle("Enable Completion", isOn: $completionEnabled) - Toggle("Include Words in Document", isOn: $completionFromDocument) - Toggle("Include Syntax Keywords", isOn: $completionFromSyntax) - Text("For lower latency on large files, keep only one completion source enabled.") - .font(Typography.footnote) - .foregroundStyle(.secondary) - } - .frame(maxWidth: .infinity, alignment: .leading) - } .frame(maxWidth: .infinity, alignment: .leading) - .padding(UI.groupPadding) } -#endif + .frame(maxWidth: .infinity, alignment: .leading) + .padding(UI.groupPadding) } +#endif } private var templateTab: some View { @@ -2311,6 +2358,7 @@ struct SettingsWindowConfigurator: NSViewRepresentable { let idealSize: NSSize let translucentEnabled: Bool let translucencyModeRaw: String + let appearanceRaw: String final class Coordinator { var didInitialApply = false @@ -2409,7 +2457,15 @@ struct SettingsWindowConfigurator: NSViewRepresentable { private func translucencyEnabledColor(enabled: Bool, window: NSWindow) -> NSColor { guard enabled else { return NSColor.windowBackgroundColor } - let isDark = window.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua + let isDark: Bool + switch appearanceRaw { + case "light": + isDark = false + case "dark": + isDark = true + default: + isDark = window.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua + } let whiteLevel: CGFloat switch translucencyModeRaw { case "subtle": diff --git a/Neon Vision Editor/UI/PanelsAndHelpers.swift b/Neon Vision Editor/UI/PanelsAndHelpers.swift index c773d10..8cde5ae 100644 --- a/Neon Vision Editor/UI/PanelsAndHelpers.swift +++ b/Neon Vision Editor/UI/PanelsAndHelpers.swift @@ -341,12 +341,12 @@ struct WelcomeTourView: View { private let pages: [TourPage] = [ TourPage( title: "What’s New in This Release", - subtitle: "Major changes since v0.5.1:", + subtitle: "Major changes since v0.5.2:", bullets: [ - "Added editor performance presets in Settings (`Balanced`, `Large Files`, `Battery`) with shared runtime mapping.", - "Added configurable project navigator placement (`Left`/`Right`) for project-structure sidebar layout.", - "Added richer updater diagnostics details in Settings: staged update summary, last install-attempt summary, and recent sanitized log snippet.", - "Added CSV/TSV table mode with a `Table`/`Text` switch, lazy row rendering, and background parsing for larger datasets." + "Added a new high-readability colorful light theme preset: `Prism Daylight` (also selectable while app appearance is set to dark).", + "Added double-click-to-close behavior for tabs on macOS tab strips.", + "Added split editor settings sections (`Basics` / `Behavior`) to reduce scrolling in the Editor tab.", + "Improved custom theme vibrancy by applying the vivid neon syntax profile to `Custom`, so syntax colors remain bright and saturated." ], iconName: "sparkles.rectangle.stack", colors: [Color(red: 0.40, green: 0.28, blue: 0.90), Color(red: 0.96, green: 0.46, blue: 0.55)], diff --git a/Neon Vision Editor/UI/ThemeSettings.swift b/Neon Vision Editor/UI/ThemeSettings.swift index 3d1545f..b9194f1 100644 --- a/Neon Vision Editor/UI/ThemeSettings.swift +++ b/Neon Vision Editor/UI/ThemeSettings.swift @@ -161,6 +161,7 @@ let editorThemeNames: [String] = [ "Plasma Storm", "Inferno Neon", "Ultraviolet Flux", + "Prism Daylight", "Custom", "Dracula", "One Dark Pro", @@ -259,14 +260,14 @@ private func paletteForThemeName(_ name: String, defaults: UserDefaults) -> Them return ThemePalette( text: Color(red: 0.94, green: 0.98, blue: 0.92), background: Color(red: 0.07, green: 0.09, blue: 0.06), - cursor: Color(red: 0.68, green: 1.00, blue: 0.20), + cursor: Color(red: 0.18, green: 0.48, blue: 0.96), selection: Color(red: 0.18, green: 0.25, blue: 0.14), - keyword: Color(red: 0.68, green: 1.00, blue: 0.20), - string: Color(red: 0.20, green: 1.00, blue: 0.78), + keyword: Color(red: 0.45, green: 0.78, blue: 0.16), + string: Color(red: 0.13, green: 0.70, blue: 0.50), number: Color(red: 1.00, green: 0.86, blue: 0.22), comment: Color(red: 0.54, green: 0.62, blue: 0.50), type: Color(red: 0.48, green: 0.86, blue: 1.00), - property: Color(red: 0.88, green: 1.00, blue: 0.36), + property: Color(red: 0.56, green: 0.78, blue: 0.28), builtin: Color(red: 1.00, green: 0.48, blue: 0.40) ) case "Plasma Storm": @@ -311,6 +312,20 @@ private func paletteForThemeName(_ name: String, defaults: UserDefaults) -> Them property: Color(red: 0.68, green: 0.72, blue: 1.00), builtin: Color(red: 1.00, green: 0.28, blue: 0.56) ) + case "Prism Daylight": + return ThemePalette( + text: Color(red: 0.08, green: 0.10, blue: 0.14), + background: Color(red: 0.96, green: 0.97, blue: 0.99), + cursor: Color(red: 0.14, green: 0.34, blue: 0.84), + selection: Color(red: 0.84, green: 0.89, blue: 0.99), + keyword: Color(red: 0.48, green: 0.13, blue: 0.71), + string: Color(red: 0.05, green: 0.48, blue: 0.33), + number: Color(red: 0.71, green: 0.28, blue: 0.03), + comment: Color(red: 0.37, green: 0.42, blue: 0.49), + type: Color(red: 0.00, green: 0.34, blue: 0.76), + property: Color(red: 0.64, green: 0.11, blue: 0.67), + builtin: Color(red: 0.76, green: 0.25, blue: 0.05) + ) case "Dracula": return ThemePalette( text: Color(red: 0.97, green: 0.97, blue: 0.95), @@ -606,7 +621,8 @@ func currentEditorTheme(colorScheme: ColorScheme) -> EditorTheme { "Cyber Lime", "Plasma Storm", "Inferno Neon", - "Ultraviolet Flux" + "Ultraviolet Flux", + "Custom" ] return vividNeonThemes.contains(name) ? .neonRaw : .standard }() diff --git a/README.md b/README.md index 674d5e7..dd11a22 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ > Status: **active release** -> Latest release: **v0.5.2** +> Latest release: **v0.5.3** > Platform target: **macOS 26 (Tahoe)** compatible with **macOS Sequoia** > Apple Silicon: tested / Intel: not tested > Last updated (README): **2026-03-10** for release line **v0.5.2** @@ -161,7 +161,7 @@ - Security policy: [`SECURITY.md`](SECURITY.md) - Release checklists: [`release/`](release/) — TestFlight & App Store preflight docs -## What's New Since v0.5.1 +## What's New Since v0.5.2 - Added `Close All Tabs` actions across macOS, iOS, and iPadOS with a confirmation safeguard. - Added project-sidebar quick actions (`Expand All` / `Collapse All`) and a default-on `Show Supported Files Only` filter. @@ -195,7 +195,7 @@ Prebuilt binaries are available on [GitHub Releases](https://github.com/h3pdesig Best for direct notarized builds and fastest access to new stable versions. - Download: [GitHub Releases](https://github.com/h3pdesign/Neon-Vision-Editor/releases) -- Latest release: **v0.5.2** +- Latest release: **v0.5.3** - Channel: **Stable** - Architecture: Apple Silicon (Intel not tested) @@ -598,15 +598,15 @@ All shortcuts use `Cmd` (`⌘`). iPad/iOS require a hardware keyboard. ## Changelog -Latest stable: **v0.5.2** (2026-03-09) +Latest stable: **v0.5.3** (2026-03-10) ### Recent Releases (At a glance) | Version | Date | Highlights | Fixes | Breaking changes | Migration | |---|---|---|---|---|---| +| [`v0.5.3`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.3) | 2026-03-10 | a new high-readability colorful light theme preset: `Prism Daylight` (also selectable while app appearance is set to dark); double-click-to-close behavior for tabs on macOS tab strips; custom theme vibrancy by applying the vivid neon syntax profile to `Custom`, so syntax colors remain bright and saturated | toolbar-symbol contrast edge cases in dark mode where gray/black variants could appear too similar | None noted | None required | | [`v0.5.2`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.2) | 2026-03-09 | editor performance presets in Settings (`Balanced`, `Large Files`, `Battery`) with shared runtime mapping; configurable project navigator placement (`Left`/`Right`) for project-structure sidebar layout; iOS/iPadOS large-file responsiveness by lowering automatic large-file thresholds and applying preset-based tuning | missing diagnostics reset workflow by adding a dedicated `Clear Diagnostics` action that also clears file-open timing snapshots; macOS editor-window top-bar jumping when toggling the toolbar translucency control by keeping chrome flags stable; CSV/TSV mode header transparency so the mode bar now uses a solid standard window background | None noted | None required | | [`v0.5.1`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.1) | 2026-03-08 | bulk `Close All Tabs` actions to toolbar surfaces (macOS, iOS, iPadOS), including a confirmation step before closing; project-structure quick actions to expand all folders or collapse all folders in one step; Markdown preview stability by preserving relative scroll position during preview refreshes | diagnostics export safety by redacting token-like updater status fragments before copying; Markdown regression coverage with new tests for Claude-style mixed-content Markdown and code-fence matching behavior; accidental destructive tab-bulk-close behavior by requiring explicit user confirmation before closing all tabs | None noted | None required | -| [`v0.5.0`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.0) | 2026-03-06 | updater staging hardening with retry/fallback behavior and staged-bundle integrity checks; explicit accessibility labels/hints for key toolbar actions and updater log/progress controls; CSV handling by enabling fast syntax profile earlier and for long-line CSV files to reduce freeze risk | updater staging resilience when `ditto` fails by retrying and falling back safely to copy-based staging; release preflight to fail on unresolved placeholder entries and stale README download metrics; inconsistent reappearance of the macOS settings tab title in the upper-left window title area | None noted | None required | - Full release history: [`CHANGELOG.md`](CHANGELOG.md) - Compare recent changes: [v0.5.0...v0.5.2](https://github.com/h3pdesign/Neon-Vision-Editor/compare/v0.5.0...v0.5.2) @@ -628,12 +628,12 @@ Latest stable: **v0.5.2** (2026-03-09) ## Release Integrity -- Tag: `v0.5.2` +- Tag: `v0.5.3` - Tagged commit: `1c31306` - Verify local tag target: ```bash -git rev-parse --verify v0.5.2 +git rev-parse --verify v0.5.3 ``` - Verify downloaded artifact checksum locally: