-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
65,517 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// | ||
// WWDCDetailView.swift | ||
// SwiftPamphletApp | ||
// | ||
// Created by Ming Dai on 2024/5/12. | ||
// | ||
|
||
import SwiftUI | ||
import AVKit | ||
import SMDate | ||
import SwiftData | ||
import InfoOrganizer | ||
|
||
struct WWDCDetailView: View { | ||
var session: WWDCSessionModel? = nil | ||
|
||
@Environment(\.modelContext) var modelContext | ||
@State private var isShowInspector = false | ||
@AppStorage(SPC.isShowWWDCInspector) var asIsShowWWDCInspector: Bool = false | ||
@Binding var limit: Int | ||
@State var selectInfo: IOInfo? = nil | ||
@Query var infos: [IOInfo] | ||
|
||
// 初始化 | ||
init(session:WWDCSessionModel, limit: Binding<Int>) { | ||
self.session = session | ||
let sid = session.id | ||
var fd = FetchDescriptor<IOInfo>(predicate: #Predicate { info in | ||
info.relateName == sid && info.isArchived == false | ||
}, sortBy: [SortDescriptor(\IOInfo.updateDate, order: .reverse)]) | ||
fd.fetchLimit = limit.wrappedValue | ||
_infos = Query(fd) | ||
self._limit = limit | ||
} | ||
|
||
var body: some View { | ||
if let ss = session { | ||
VStack { | ||
if selectInfo == nil { | ||
VStack(spacing: 10) { | ||
HStack { | ||
Spacer() | ||
Text(ss.title) | ||
.font(.title) | ||
Spacer() | ||
Button("相关资料管理") { | ||
isShowInspector.toggle() | ||
} | ||
} | ||
if let vurl = ss.media.videoOriginalUrl { | ||
VideoPlayer(player: AVPlayer(url: URL(string: vurl)!)) | ||
} | ||
Text(ss.description ?? "") | ||
Spacer() | ||
} | ||
.padding(20) | ||
} else { | ||
if let info = selectInfo { | ||
EditInfoView(info: info) | ||
} else { | ||
EmptyView() | ||
} | ||
} | ||
} | ||
.inspector(isPresented: $isShowInspector) { | ||
HStack { | ||
// 关闭 | ||
Button(action: { | ||
isShowInspector = false | ||
selectInfo = nil | ||
}, label: { | ||
Image(systemName: "xmark.circle") | ||
}) | ||
.help("command + d") | ||
.keyboardShortcut(KeyEquivalent("d"), modifiers: .command) | ||
Spacer() | ||
Text("资料") | ||
.font(.title) | ||
Spacer() | ||
Button("添加资料") { | ||
let info = IOInfo(name: "新增\(session?.id ?? "")资料 - \(SMDate.nowDateString())", url: "", des: "", relateName: session?.id ?? "") | ||
modelContext.insert(info) | ||
selectInfo = info | ||
} | ||
} | ||
.padding(EdgeInsets(top: 10, leading: 10, bottom: 2, trailing: 10)) | ||
List(selection: $selectInfo) { | ||
ForEach(infos) { info in | ||
InfoRowView(info: info) | ||
.tag(info) | ||
.id(info) | ||
.onAppear { | ||
if info == infos.last { | ||
if limit <= infos.count { | ||
limit += 50 | ||
} | ||
} | ||
} | ||
} | ||
} | ||
.listStyle(.plain) | ||
} | ||
.onAppear { | ||
isShowInspector = asIsShowWWDCInspector | ||
} | ||
.onChange(of: session) { oldValue, newValue in | ||
selectInfo = nil | ||
} | ||
.onChange(of: isShowInspector) { oldValue, newValue in | ||
asIsShowWWDCInspector = newValue | ||
} | ||
|
||
} else { | ||
EmptyView() | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// | ||
// WWDCListView.swift | ||
// SwiftPamphletApp | ||
// | ||
// Created by Ming Dai on 2024/5/12. | ||
// | ||
|
||
import SwiftUI | ||
|
||
struct WWDCListView: View { | ||
@State private var wwdcData: [WWDCModelForOutline] = [WWDCModelForOutline]() | ||
@State private var limit: Int = 50 | ||
var body: some View { | ||
SPOutlineListView(d: wwdcData, c: \.sub, content: { item in | ||
VStack { | ||
if let session = item.session { | ||
NavigationLink(destination: WWDCDetailView(session: session, limit: $limit)) { | ||
// if item.sub?.count ?? 0 > 0 { | ||
// Text(item.text) | ||
// } else { | ||
// | ||
// | ||
// } | ||
VStack(alignment: .leading) { | ||
Text(session.title) | ||
HStack { | ||
Text(simpleSessionid(id: session.id)) | ||
Text(session.topic) | ||
} | ||
.font(.footnote) | ||
.foregroundStyle(.secondary) | ||
} | ||
} | ||
.contentShape(Rectangle()) | ||
} else { | ||
Text(item.text) | ||
} | ||
} | ||
}) | ||
.listStyle(.sidebar) | ||
.onAppear { | ||
wwdcData = WWDCViewModel.parseModelForOutline() | ||
} | ||
|
||
} | ||
|
||
func simpleSessionid(id: String) -> String { | ||
let arr = id.split(separator: "-") | ||
if arr.count > 1 { | ||
return "session " + (arr.last?.description ?? "") | ||
} | ||
return "" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// | ||
// WWDCModel.swift | ||
// SwiftPamphletApp | ||
// | ||
// Created by Ming Dai on 2024/5/11. | ||
// | ||
|
||
import Foundation | ||
import SMFile | ||
|
||
protocol Jsonable : Identifiable, Decodable, Hashable {} | ||
|
||
struct WWDCViewModel { | ||
|
||
static func parseModelForOutline() -> [WWDCModelForOutline] { | ||
let model:WWDCModel = SMFile.loadBundleJSONFile("WWDCData.json") | ||
|
||
var reModel = [WWDCModelForOutline]() | ||
for event in model.events { | ||
reModel.append(WWDCModelForOutline(text: event.name, eventid: event.id, sub: [WWDCModelForOutline]())) | ||
} | ||
for session in model.sessions { | ||
for (index,eo) in reModel.enumerated() { | ||
if session.eventId == eo.eventid { | ||
reModel[index].sub?.append(WWDCModelForOutline(session: session)) | ||
} | ||
} | ||
} | ||
return reModel.reversed() | ||
} | ||
|
||
} | ||
|
||
// MARK: Model for View | ||
struct WWDCModelForOutline: Identifiable { | ||
var id = UUID() | ||
var text: String = "" | ||
var eventid: String = "" | ||
var session: WWDCSessionModel? | ||
var sub: [WWDCModelForOutline]? | ||
} | ||
|
||
// MARK: Model for json | ||
struct WWDCModel: Decodable, Hashable { | ||
var sessions: [WWDCSessionModel] | ||
var events: [WWDCEvent] | ||
} | ||
|
||
struct WWDCSessionModel: Jsonable { | ||
var id: String | ||
var title: String | ||
var description: String? | ||
var eventId: String | ||
var eventContentId: String | ||
var topic: String | ||
var platforms: [String]? | ||
var speakers: [String]? | ||
var appleWeblink: String? | ||
var media: WWDCMedia | ||
} | ||
|
||
struct WWDCMedia: Decodable, Hashable { | ||
var duration: Int? | ||
var videoOriginalFilename: String? | ||
var videoOriginalUrl: String? | ||
var videoFilename: String? | ||
} | ||
|
||
struct WWDCEvent: Jsonable { | ||
var id: String | ||
var name: String | ||
var description: String | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.