updates
This commit is contained in:
@@ -6,7 +6,7 @@ struct WorkbenchReplacementApp: App {
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup("Workbench Replacement") {
|
||||
MainView()
|
||||
WorkbenchLaunchView()
|
||||
.environmentObject(model)
|
||||
.frame(minWidth: 1000, minHeight: 650)
|
||||
}
|
||||
@@ -297,3 +297,96 @@ struct WorkbenchSettingsView: View {
|
||||
.frame(height: 30)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Splash Screen
|
||||
|
||||
struct WorkbenchLaunchView: View {
|
||||
@State private var showingSplash = true
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
MainView()
|
||||
|
||||
if showingSplash {
|
||||
WorkbenchSplashView()
|
||||
.transition(.opacity)
|
||||
.zIndex(10)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? await Task.sleep(for: .seconds(3))
|
||||
|
||||
withAnimation(.easeOut(duration: 0.4)) {
|
||||
showingSplash = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkbenchSplashView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Spacer()
|
||||
|
||||
if let path = Bundle.main.path(
|
||||
forResource: "WorkbenchBrand",
|
||||
ofType: "png"
|
||||
), let image = NSImage(contentsOfFile: path) {
|
||||
Image(nsImage: image)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 160, height: 160)
|
||||
}
|
||||
|
||||
Text("Workbench Replacement")
|
||||
.font(.system(size: 30, weight: .bold))
|
||||
|
||||
Text("Modern MySQL Client for macOS")
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
HStack(spacing: 30) {
|
||||
feature("cylinder.split.1x2", "Schemas")
|
||||
feature("chevron.left.forwardslash.chevron.right", "SQL Editor")
|
||||
feature("tablecells", "Result Grid")
|
||||
feature("server.rack", "Connections")
|
||||
}
|
||||
.padding(.top, 20)
|
||||
|
||||
Spacer()
|
||||
|
||||
ProgressView()
|
||||
.frame(width: 260)
|
||||
|
||||
Text("Starting Workbench Replacement…")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.bottom, 30)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color(red: 0.96, green: 0.98, blue: 1),
|
||||
Color(red: 0.88, green: 0.93, blue: 1)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
.preferredColorScheme(.light)
|
||||
}
|
||||
|
||||
private func feature(_ symbol: String, _ title: String) -> some View {
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: symbol)
|
||||
.font(.system(size: 24))
|
||||
.foregroundStyle(.blue)
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 12))
|
||||
}
|
||||
.frame(width: 90)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct WorkbenchReplacementApp: App {
|
||||
@StateObject private var model = DatabaseModel()
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup("Workbench Replacement") {
|
||||
MainView()
|
||||
.environmentObject(model)
|
||||
.frame(minWidth: 1000, minHeight: 650)
|
||||
}
|
||||
.commands {
|
||||
CommandGroup(replacing: .newItem) {}
|
||||
}
|
||||
|
||||
|
||||
Settings {
|
||||
WorkbenchSettingsView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Application Preferences
|
||||
|
||||
@MainActor
|
||||
final class WorkbenchPreferences: ObservableObject {
|
||||
static let shared = WorkbenchPreferences()
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.appearance")
|
||||
var appearance = "light"
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
var autoExpandTables = true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Settings
|
||||
|
||||
struct WorkbenchSettingsView: View {
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
private var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
private var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
private var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
private var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.defaultRowLimit")
|
||||
private var defaultRowLimit = 500
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
private var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
private var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
private var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
private var autoExpandTables = true
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
|
||||
editorSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"SQL Editor",
|
||||
systemImage: "chevron.left.forwardslash.chevron.right"
|
||||
)
|
||||
}
|
||||
|
||||
executionSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"Query Execution",
|
||||
systemImage: "bolt"
|
||||
)
|
||||
}
|
||||
|
||||
resultSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"Result Grid",
|
||||
systemImage: "tablecells"
|
||||
)
|
||||
}
|
||||
|
||||
generalSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"General",
|
||||
systemImage: "gearshape"
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(width: 620, height: 390)
|
||||
.preferredColorScheme(.light)
|
||||
}
|
||||
|
||||
private var editorSettings: some View {
|
||||
settingsPage("SQL Editor") {
|
||||
|
||||
settingsRow("Font Size") {
|
||||
Stepper(
|
||||
"\(Int(editorFontSize)) pt",
|
||||
value: $editorFontSize,
|
||||
in: 10...24,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Tab Width") {
|
||||
Picker("", selection: $tabWidth) {
|
||||
Text("2 spaces").tag(2)
|
||||
Text("4 spaces").tag(4)
|
||||
Text("8 spaces").tag(8)
|
||||
}
|
||||
.labelsHidden()
|
||||
.frame(width: 150)
|
||||
}
|
||||
|
||||
settingsRow("SQL Formatting") {
|
||||
Toggle(
|
||||
"Automatically uppercase SQL keywords",
|
||||
isOn: $uppercaseKeywords
|
||||
)
|
||||
}
|
||||
|
||||
settingsRow("Editor Display") {
|
||||
Toggle(
|
||||
"Show line numbers",
|
||||
isOn: $showLineNumbers
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var executionSettings: some View {
|
||||
settingsPage("Query Execution") {
|
||||
|
||||
settingsRow("Default Row Limit") {
|
||||
HStack(spacing: 12) {
|
||||
TextField(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
format: .number
|
||||
)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 110)
|
||||
|
||||
Stepper(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
in: 50...100000,
|
||||
step: 50
|
||||
)
|
||||
.labelsHidden()
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
"Controls the number of rows retrieved when opening a table from the schema navigator."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.leading, 190)
|
||||
|
||||
Divider()
|
||||
.padding(.vertical, 12)
|
||||
|
||||
Text("Examples")
|
||||
.font(.headline)
|
||||
|
||||
Text(
|
||||
"500 rows: Faster browsing and lower memory usage.\n" +
|
||||
"5,000 rows: Useful for larger datasets.\n" +
|
||||
"50,000 rows: May take longer to retrieve."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
|
||||
private var resultSettings: some View {
|
||||
settingsPage("Result Grid") {
|
||||
|
||||
settingsRow("Row Height") {
|
||||
Stepper(
|
||||
"\(Int(resultRowHeight)) px",
|
||||
value: $resultRowHeight,
|
||||
in: 18...40,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Column Width") {
|
||||
Stepper(
|
||||
"\(Int(resultColumnWidth)) px",
|
||||
value: $resultColumnWidth,
|
||||
in: 80...400,
|
||||
step: 10
|
||||
)
|
||||
.frame(width: 140)
|
||||
}
|
||||
|
||||
settingsRow("Appearance") {
|
||||
Toggle(
|
||||
"Alternating row colours",
|
||||
isOn: $alternatingRows
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var generalSettings: some View {
|
||||
settingsPage("General") {
|
||||
|
||||
settingsRow("Navigator") {
|
||||
Toggle(
|
||||
"Automatically expand table folders",
|
||||
isOn: $autoExpandTables
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func settingsPage<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
|
||||
Divider()
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(26)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color(nsColor: .windowBackgroundColor))
|
||||
}
|
||||
|
||||
private func settingsRow<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
HStack(alignment: .center, spacing: 16) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 13))
|
||||
.frame(width: 170, alignment: .trailing)
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.frame(height: 30)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 530 KiB |
Binary file not shown.
Reference in New Issue
Block a user