feat 使用SwiftUI的方式调整窗口大小
This commit is contained in:
parent
4c373b7e5e
commit
b10f99ac8a
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user