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 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
}
}

View File

@ -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

View File

@ -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())
}

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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)
}
}