feat 使用SwiftUI的方式调整窗口大小

This commit is contained in:
seahi 2025-03-20 09:49:53 +08:00
parent 4c373b7e5e
commit b10f99ac8a
6 changed files with 81 additions and 49 deletions

View File

@ -7,9 +7,23 @@
import SwiftUI import SwiftUI
import SwiftData import SwiftData
#if os(macOS)
import AppKit
#endif
// Class to manage window title across the app
class WindowTitleManager: ObservableObject {
@Published var title: String = "TeachMate"
func updateTitle(_ newTitle: String) {
self.title = newTitle
}
}
@main @main
struct TeachMateApp: App { struct TeachMateApp: App {
@StateObject private var windowTitleManager = WindowTitleManager()
var sharedModelContainer: ModelContainer = { var sharedModelContainer: ModelContainer = {
let schema = Schema([ let schema = Schema([
Semester.self, Semester.self,
@ -28,7 +42,17 @@ struct TeachMateApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView() ContentView()
.environmentObject(windowTitleManager)
.onReceive(windowTitleManager.$title) { newTitle in
#if os(macOS)
NSApp.windows.first?.title = newTitle
#endif
}
} }
.modelContainer(sharedModelContainer) .modelContainer(sharedModelContainer)
#if os(macOS)
.windowResizability(.contentSize)
.defaultSize(WindowSizeManager.WindowSizePreset.schedule.size)
#endif
} }
} }

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
#if os(macOS) #if os(macOS)
// //
struct WindowSizeManager { struct WindowSizeManager {
enum WindowSizePreset { enum WindowSizePreset {
case calendar // - case calendar // -
@ -17,52 +17,29 @@ struct WindowSizeManager {
var size: CGSize { var size: CGSize {
switch self { switch self {
case .calendar: case .calendar:
return CGSize(width: 500, height: 800) // return CGSize(width: 500, height: 800)
case .schedule: case .schedule:
return CGSize(width: 1200, height: 680) // return CGSize(width: 1200, height: 680)
} }
} }
} }
}
//
static func resizeWindow(to preset: WindowSizePreset) { // Scene便使
guard let window = NSApplication.shared.windows.first else { return } extension Scene {
func windowIdealSize(_ preset: WindowSizeManager.WindowSizePreset) -> some Scene {
let newSize = preset.size self.windowResizability(.contentSize)
let currentFrame = window.frame .defaultSize(preset.size)
//
let newOriginX = currentFrame.origin.x + (currentFrame.width - newSize.width) / 2
let newOriginY = currentFrame.origin.y + (currentFrame.height - newSize.height) / 2
let newFrame = NSRect(
x: newOriginX,
y: newOriginY,
width: newSize.width,
height: newSize.height
)
//
window.animator().setFrame(newFrame, display: true, animate: true)
} }
} }
// // View便
struct WindowSizeModifier: ViewModifier {
let preset: WindowSizeManager.WindowSizePreset
func body(content: Content) -> some View {
content
.onAppear {
WindowSizeManager.resizeWindow(to: preset)
}
}
}
// View便使
extension View { extension View {
func adjustWindowSize(to preset: WindowSizeManager.WindowSizePreset) -> some View { func idealFrame(for preset: WindowSizeManager.WindowSizePreset) -> some View {
modifier(WindowSizeModifier(preset: preset)) self.frame(
idealWidth: preset.size.width,
idealHeight: preset.size.height
)
} }
} }
#endif #endif

View File

@ -11,6 +11,7 @@ import SwiftData
struct ContentView: View { struct ContentView: View {
@Environment(\.modelContext) private var modelContext @Environment(\.modelContext) private var modelContext
@Query private var semesters: [Semester] @Query private var semesters: [Semester]
@EnvironmentObject private var windowTitleManager: WindowTitleManager
// Add a state to track the selected navigation item // Add a state to track the selected navigation item
@State private var selectedNavItem: NavItem? = .schedule @State private var selectedNavItem: NavItem? = .schedule
@ -120,14 +121,20 @@ struct ContentView: View {
CourseScheduleView(semester: currentSemester) CourseScheduleView(semester: currentSemester)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
#if os(macOS) #if os(macOS)
.adjustWindowSize(to: .schedule) .idealFrame(for: .schedule)
#endif #endif
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} else if !semesters.isEmpty { } else if !semesters.isEmpty {
CourseScheduleView(semester: semesters[0]) CourseScheduleView(semester: semesters[0])
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
#if os(macOS) #if os(macOS)
.adjustWindowSize(to: .schedule) .idealFrame(for: .schedule)
#endif #endif
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} else { } else {
VStack { VStack {
Text("请先添加学期") Text("请先添加学期")
@ -135,20 +142,29 @@ struct ContentView: View {
Text("在添加学期后,将自动显示课程表") Text("在添加学期后,将自动显示课程表")
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} }
case .calendar: case .calendar:
if let currentSemester = semesters.first(where: { $0.isCurrent }) { if let currentSemester = semesters.first(where: { $0.isCurrent }) {
AcademicCalendarView(semester: currentSemester) AcademicCalendarView(semester: currentSemester)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
#if os(macOS) #if os(macOS)
.adjustWindowSize(to: .calendar) .idealFrame(for: .calendar)
#endif #endif
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} else if !semesters.isEmpty { } else if !semesters.isEmpty {
AcademicCalendarView(semester: semesters[0]) AcademicCalendarView(semester: semesters[0])
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
#if os(macOS) #if os(macOS)
.adjustWindowSize(to: .calendar) .idealFrame(for: .calendar)
#endif #endif
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} else { } else {
VStack { VStack {
Text("请先添加学期") Text("请先添加学期")
@ -156,11 +172,20 @@ struct ContentView: View {
Text("在添加学期后,将自动显示教学日历") Text("在添加学期后,将自动显示教学日历")
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} }
case .reminders: case .reminders:
Text("提醒事项内容") Text("提醒事项内容")
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
case .courseManager: case .courseManager:
CourseManagerView() CourseManagerView()
.onAppear {
windowTitleManager.updateTitle(selectedNavItem.rawValue)
}
} }
} else if let semester = selectedSemester { } else if let semester = selectedSemester {
// Show semester detail // Show semester detail
@ -199,9 +224,14 @@ struct ContentView: View {
Spacer() Spacer()
} }
.padding() .padding()
.frame(maxWidth: .infinity, alignment: .leading) .onAppear {
windowTitleManager.updateTitle(semester.title)
}
} else { } else {
Text("请选择一个项目") Text("选择一个项目以查看详情")
.onAppear {
windowTitleManager.updateTitle("TeachMate")
}
} }
} }
} }
@ -228,4 +258,5 @@ struct ContentView: View {
#Preview { #Preview {
ContentView() ContentView()
.modelContainer(PreviewData.createSemesterContainer()) .modelContainer(PreviewData.createSemesterContainer())
.environmentObject(WindowTitleManager())
} }

View File

@ -64,6 +64,7 @@ struct CourseFormView: View {
setupInitialValues() setupInitialValues()
} }
} }
.frame(idealWidth: 600, idealHeight: 400)
} }
// Main content view // Main content view
@ -78,7 +79,6 @@ struct CourseFormView: View {
// Left side - Form content // Left side - Form content
formFieldsSection formFieldsSection
} }
.frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity)
} }
} }

View File

@ -87,7 +87,7 @@ struct CourseManagerView: View {
mode: .edit(course), mode: .edit(course),
onSave: { _ in } onSave: { _ in }
) )
.frame(width: 600) .frame(idealWidth: 600, idealHeight: 400)
} else { } else {
CourseFormView( CourseFormView(
mode: .add, mode: .add,
@ -96,7 +96,7 @@ struct CourseManagerView: View {
selectedCourse = newCourse selectedCourse = newCourse
} }
) )
.frame(width: 600) .frame(idealWidth: 600, idealHeight: 400)
} }
} }
.onAppear { .onAppear {

View File

@ -58,6 +58,7 @@ struct SessionFormView: View {
setupInitialValues() setupInitialValues()
} }
} }
.frame(idealWidth: 600, idealHeight: 400)
} }
// Main content view // Main content view
@ -76,7 +77,6 @@ struct SessionFormView: View {
Divider() Divider()
.padding(.vertical) .padding(.vertical)
} }
.frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity)
} }
} }