diff --git a/TeachMate/TeachMateApp.swift b/TeachMate/TeachMateApp.swift index e5a7142..0e354f6 100644 --- a/TeachMate/TeachMateApp.swift +++ b/TeachMate/TeachMateApp.swift @@ -7,9 +7,23 @@ import SwiftUI 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 struct TeachMateApp: App { + @StateObject private var windowTitleManager = WindowTitleManager() + var sharedModelContainer: ModelContainer = { let schema = Schema([ Semester.self, @@ -28,7 +42,17 @@ struct TeachMateApp: App { var body: some Scene { WindowGroup { ContentView() + .environmentObject(windowTitleManager) + .onReceive(windowTitleManager.$title) { newTitle in + #if os(macOS) + NSApp.windows.first?.title = newTitle + #endif + } } .modelContainer(sharedModelContainer) + #if os(macOS) + .windowResizability(.contentSize) + .defaultSize(WindowSizeManager.WindowSizePreset.schedule.size) + #endif } } diff --git a/TeachMate/Utilities/WindowSizeManager.swift b/TeachMate/Utilities/WindowSizeManager.swift index 093bc0d..c8ae399 100644 --- a/TeachMate/Utilities/WindowSizeManager.swift +++ b/TeachMate/Utilities/WindowSizeManager.swift @@ -8,7 +8,7 @@ import SwiftUI #if os(macOS) -// 窗口尺寸管理器 +// 窗口尺寸预设 struct WindowSizeManager { enum WindowSizePreset { case calendar // 教学历视图 - 竖长 @@ -17,52 +17,29 @@ struct WindowSizeManager { var size: CGSize { switch self { case .calendar: - return CGSize(width: 500, height: 800) // 竖长窗口 + return CGSize(width: 500, height: 800) case .schedule: - return CGSize(width: 1200, height: 680) // 横长窗口 + return CGSize(width: 1200, height: 680) } } } - - // 调整窗口大小 - static func resizeWindow(to preset: WindowSizePreset) { - guard let window = NSApplication.shared.windows.first else { return } - - let newSize = preset.size - let currentFrame = window.frame - - // 计算新的窗口位置,保持窗口中心点不变 - 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) +} + +// 扩展Scene以便于使用 +extension Scene { + func windowIdealSize(_ preset: WindowSizeManager.WindowSizePreset) -> some Scene { + self.windowResizability(.contentSize) + .defaultSize(preset.size) } } -// 视图修饰符,用于调整窗口大小 -struct WindowSizeModifier: ViewModifier { - let preset: WindowSizeManager.WindowSizePreset - - func body(content: Content) -> some View { - content - .onAppear { - WindowSizeManager.resizeWindow(to: preset) - } - } -} - -// 扩展View以便于使用 +// 扩展View以便于在视图级别设置理想尺寸 extension View { - func adjustWindowSize(to preset: WindowSizeManager.WindowSizePreset) -> some View { - modifier(WindowSizeModifier(preset: preset)) + func idealFrame(for preset: WindowSizeManager.WindowSizePreset) -> some View { + self.frame( + idealWidth: preset.size.width, + idealHeight: preset.size.height + ) } } #endif diff --git a/TeachMate/Views/ContentView.swift b/TeachMate/Views/ContentView.swift index 71327a0..9d7018d 100644 --- a/TeachMate/Views/ContentView.swift +++ b/TeachMate/Views/ContentView.swift @@ -11,6 +11,7 @@ import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var semesters: [Semester] + @EnvironmentObject private var windowTitleManager: WindowTitleManager // Add a state to track the selected navigation item @State private var selectedNavItem: NavItem? = .schedule @@ -120,14 +121,20 @@ struct ContentView: View { CourseScheduleView(semester: currentSemester) .frame(maxWidth: .infinity, maxHeight: .infinity) #if os(macOS) - .adjustWindowSize(to: .schedule) + .idealFrame(for: .schedule) #endif + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } else if !semesters.isEmpty { CourseScheduleView(semester: semesters[0]) .frame(maxWidth: .infinity, maxHeight: .infinity) #if os(macOS) - .adjustWindowSize(to: .schedule) + .idealFrame(for: .schedule) #endif + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } else { VStack { Text("请先添加学期") @@ -135,20 +142,29 @@ struct ContentView: View { Text("在添加学期后,将自动显示课程表") .foregroundColor(.secondary) } + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } case .calendar: if let currentSemester = semesters.first(where: { $0.isCurrent }) { AcademicCalendarView(semester: currentSemester) .frame(maxWidth: .infinity, maxHeight: .infinity) #if os(macOS) - .adjustWindowSize(to: .calendar) + .idealFrame(for: .calendar) #endif + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } else if !semesters.isEmpty { AcademicCalendarView(semester: semesters[0]) .frame(maxWidth: .infinity, maxHeight: .infinity) #if os(macOS) - .adjustWindowSize(to: .calendar) + .idealFrame(for: .calendar) #endif + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } else { VStack { Text("请先添加学期") @@ -156,11 +172,20 @@ struct ContentView: View { Text("在添加学期后,将自动显示教学日历") .foregroundColor(.secondary) } + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } case .reminders: Text("提醒事项内容") + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } case .courseManager: CourseManagerView() + .onAppear { + windowTitleManager.updateTitle(selectedNavItem.rawValue) + } } } else if let semester = selectedSemester { // Show semester detail @@ -199,9 +224,14 @@ struct ContentView: View { Spacer() } .padding() - .frame(maxWidth: .infinity, alignment: .leading) + .onAppear { + windowTitleManager.updateTitle(semester.title) + } } else { - Text("请选择一个项目") + Text("选择一个项目以查看详情") + .onAppear { + windowTitleManager.updateTitle("TeachMate") + } } } } @@ -228,4 +258,5 @@ struct ContentView: View { #Preview { ContentView() .modelContainer(PreviewData.createSemesterContainer()) + .environmentObject(WindowTitleManager()) } diff --git a/TeachMate/Views/CourseFormView.swift b/TeachMate/Views/CourseFormView.swift index 09fe207..7a3f7a9 100644 --- a/TeachMate/Views/CourseFormView.swift +++ b/TeachMate/Views/CourseFormView.swift @@ -64,6 +64,7 @@ struct CourseFormView: View { setupInitialValues() } } + .frame(idealWidth: 600, idealHeight: 400) } // Main content view @@ -78,7 +79,6 @@ struct CourseFormView: View { // Left side - Form content formFieldsSection } - .frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity) } } diff --git a/TeachMate/Views/CourseManagerView.swift b/TeachMate/Views/CourseManagerView.swift index 069ffd4..dc9e350 100644 --- a/TeachMate/Views/CourseManagerView.swift +++ b/TeachMate/Views/CourseManagerView.swift @@ -87,7 +87,7 @@ struct CourseManagerView: View { mode: .edit(course), onSave: { _ in } ) - .frame(width: 600) + .frame(idealWidth: 600, idealHeight: 400) } else { CourseFormView( mode: .add, @@ -96,7 +96,7 @@ struct CourseManagerView: View { selectedCourse = newCourse } ) - .frame(width: 600) + .frame(idealWidth: 600, idealHeight: 400) } } .onAppear { diff --git a/TeachMate/Views/SessionFormView.swift b/TeachMate/Views/SessionFormView.swift index d0cead2..737e23d 100644 --- a/TeachMate/Views/SessionFormView.swift +++ b/TeachMate/Views/SessionFormView.swift @@ -58,6 +58,7 @@ struct SessionFormView: View { setupInitialValues() } } + .frame(idealWidth: 600, idealHeight: 400) } // Main content view @@ -76,7 +77,6 @@ struct SessionFormView: View { Divider() .padding(.vertical) } - .frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity) } }