Rework content commands, add audio player
This commit is contained in:
@ -0,0 +1,94 @@
|
||||
import Foundation
|
||||
|
||||
struct AudioPlayerCommandProcessor: CommandProcessor {
|
||||
|
||||
let commandType: ShorthandMarkdownKey = .audioPlayer
|
||||
|
||||
let content: Content
|
||||
|
||||
let results: PageGenerationResults
|
||||
|
||||
init(content: Content, results: PageGenerationResults) {
|
||||
self.content = content
|
||||
self.results = results
|
||||
}
|
||||
|
||||
func process(_ arguments: [String], markdown: Substring) -> String {
|
||||
guard arguments.count == 2 else {
|
||||
results.invalid(command: .audioPlayer, "Invalid audio player arguments")
|
||||
return ""
|
||||
}
|
||||
let fileId = arguments[0]
|
||||
let titleText = arguments[1]
|
||||
|
||||
guard content.isValidIdForFile(fileId) else {
|
||||
results.invalid(command: .audioPlayer, "Invalid file id \(fileId) for audio player")
|
||||
return ""
|
||||
}
|
||||
|
||||
guard let file = content.file(fileId) else {
|
||||
results.missingFiles.insert(fileId)
|
||||
return ""
|
||||
}
|
||||
let songs: [Song]
|
||||
do {
|
||||
let data = try file.dataContent()
|
||||
songs = try JSONDecoder().decode([Song].self, from: data)
|
||||
} catch {
|
||||
results.issues.insert(.failedToLoadContent(error))
|
||||
return ""
|
||||
}
|
||||
|
||||
var playlist: [AudioPlayer.PlaylistItem] = []
|
||||
var amplitude: [AmplitudeSong] = []
|
||||
|
||||
for song in songs {
|
||||
guard let image = content.image(song.cover) else {
|
||||
results.missing(file: song.cover, markdown: "Missing cover image \(song.cover) in \(file.id)")
|
||||
continue
|
||||
}
|
||||
|
||||
guard let audioFile = content.file(song.file) else {
|
||||
results.missing(file: song.file, markdown: "Missing audio file \(song.file) in \(file.id)")
|
||||
continue
|
||||
}
|
||||
#warning("Check if file is audio")
|
||||
let coverUrl = image.absoluteUrl
|
||||
|
||||
let playlistItem = AudioPlayer.PlaylistItem(
|
||||
index: playlist.count,
|
||||
image: coverUrl,
|
||||
name: song.name,
|
||||
album: song.album,
|
||||
track: song.track,
|
||||
artist: song.artist)
|
||||
|
||||
let amplitudeSong = AmplitudeSong(
|
||||
name: song.name,
|
||||
artist: song.artist,
|
||||
album: song.album,
|
||||
track: "\(song.track)",
|
||||
url: audioFile.absoluteUrl,
|
||||
cover_art_url: coverUrl)
|
||||
|
||||
playlist.append(playlistItem)
|
||||
amplitude.append(amplitudeSong)
|
||||
}
|
||||
|
||||
let footerScript = AudioPlayerScript(items: amplitude).content
|
||||
results.requiredFooters.insert(footerScript)
|
||||
results.requiredHeaders.insert(.audioPlayerCss)
|
||||
results.requiredHeaders.insert(.amplitude)
|
||||
|
||||
results.requiredIcons.formUnion([
|
||||
.audioPlayerClose,
|
||||
.audioPlayerPlaylist,
|
||||
.audioPlayerNext,
|
||||
.audioPlayerPrevious,
|
||||
.audioPlayerPlay,
|
||||
.audioPlayerPause
|
||||
])
|
||||
|
||||
return AudioPlayer(playingText: titleText, items: playlist).content
|
||||
}
|
||||
}
|
103
CHDataManagement/Generator/Page Content/ButtonCommand.swift
Normal file
103
CHDataManagement/Generator/Page Content/ButtonCommand.swift
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
struct ButtonCommandProcessor: CommandProcessor {
|
||||
|
||||
let commandType: ShorthandMarkdownKey = .buttons
|
||||
|
||||
let content: Content
|
||||
|
||||
let results: PageGenerationResults
|
||||
|
||||
init(content: Content, results: PageGenerationResults) {
|
||||
self.content = content
|
||||
self.results = results
|
||||
}
|
||||
|
||||
/**
|
||||
Format: ``
|
||||
Format: ``
|
||||
Types:
|
||||
- Download: `download=<fileId>,<text>,<download-filename?>`
|
||||
- External link: `external=<url>,<text>`
|
||||
- Git: `git=<url>,<text>`
|
||||
- Play: `play-circle=<text>,<click-action>`
|
||||
*/
|
||||
func process(_ arguments: [String], markdown: Substring) -> String {
|
||||
let buttons = arguments.compactMap { convert(button: $0, markdown: markdown) }
|
||||
return ContentButtons(items: buttons).content
|
||||
}
|
||||
|
||||
private func convert(button: String, markdown: Substring) -> ContentButtons.Item? {
|
||||
guard let type = PageIcon(rawValue: button.dropAfterFirst("=").trimmed) else {
|
||||
results.invalid(command: commandType, markdown)
|
||||
return nil
|
||||
}
|
||||
let parts = button.dropBeforeFirst("=").components(separatedBy: ",").map { $0.trimmed }
|
||||
switch type {
|
||||
case .buttonDownload:
|
||||
return download(arguments: parts, markdown: markdown)
|
||||
case .buttonGitLink:
|
||||
return link(icon: .buttonGitLink, arguments: parts, markdown: markdown)
|
||||
case .buttonExternalLink:
|
||||
return link(icon: .buttonExternalLink, arguments: parts, markdown: markdown)
|
||||
case .buttonPlay:
|
||||
return play(arguments: parts, markdown: markdown)
|
||||
default:
|
||||
results.invalid(command: commandType, markdown)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func download(arguments: [String], markdown: Substring) -> ContentButtons.Item? {
|
||||
guard (2...3).contains(arguments.count) else {
|
||||
results.invalid(command: commandType, markdown)
|
||||
return nil
|
||||
}
|
||||
let fileId = arguments[0].trimmed
|
||||
let title = arguments[1].trimmed
|
||||
let downloadName = arguments.count > 2 ? arguments[2].trimmed : nil
|
||||
|
||||
guard let file = content.file(fileId) else {
|
||||
results.missing(file: fileId, markdown: markdown)
|
||||
return nil
|
||||
}
|
||||
results.files.insert(file)
|
||||
results.requiredIcons.insert(.buttonDownload)
|
||||
return ContentButtons.Item(
|
||||
icon: .buttonDownload,
|
||||
filePath: file.absoluteUrl,
|
||||
text: title,
|
||||
downloadFileName: downloadName)
|
||||
}
|
||||
|
||||
private func link(icon: PageIcon, arguments: [String], markdown: Substring) -> ContentButtons.Item? {
|
||||
guard arguments.count == 2 else {
|
||||
results.invalid(command: .buttons, markdown)
|
||||
return nil
|
||||
}
|
||||
let rawUrl = arguments[0].trimmed
|
||||
guard let url = rawUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
|
||||
results.invalid(command: .buttons, markdown)
|
||||
return nil
|
||||
}
|
||||
|
||||
results.externalLinks.insert(rawUrl)
|
||||
results.requiredIcons.insert(icon)
|
||||
|
||||
let title = arguments[1].trimmed
|
||||
|
||||
return .init(icon: icon, filePath: url, text: title)
|
||||
}
|
||||
|
||||
private func play(arguments: [String], markdown: Substring) -> ContentButtons.Item? {
|
||||
guard arguments.count == 2 else {
|
||||
results.invalid(command: .buttons, markdown)
|
||||
return nil
|
||||
}
|
||||
let text = arguments[0].trimmed
|
||||
let event = arguments[1].trimmed
|
||||
|
||||
results.requiredIcons.insert(.buttonPlay)
|
||||
|
||||
return .init(icon: .buttonPlay, filePath: nil, text: text, onClickText: event)
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
|
||||
protocol CommandProcessor {
|
||||
|
||||
var commandType: ShorthandMarkdownKey { get }
|
||||
|
||||
init(content: Content, results: PageGenerationResults)
|
||||
|
||||
func process(_ arguments: [String], markdown: Substring) -> String
|
||||
}
|
30
CHDataManagement/Generator/Page Content/LabelsCommand.swift
Normal file
30
CHDataManagement/Generator/Page Content/LabelsCommand.swift
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
struct LabelsCommandProcessor: CommandProcessor {
|
||||
|
||||
let commandType: ShorthandMarkdownKey = .labels
|
||||
|
||||
let content: Content
|
||||
|
||||
let results: PageGenerationResults
|
||||
|
||||
init(content: Content, results: PageGenerationResults) {
|
||||
self.content = content
|
||||
self.results = results
|
||||
}
|
||||
|
||||
func process(_ arguments: [String], markdown: Substring) -> String {
|
||||
let labels: [ContentLabel] = arguments.compactMap { arg in
|
||||
let parts = arg.components(separatedBy: "=")
|
||||
guard parts.count == 2 else {
|
||||
results.invalid(command: .labels, markdown)
|
||||
return nil
|
||||
}
|
||||
guard let icon = PageIcon(rawValue: parts[0].trimmed) else {
|
||||
results.invalid(command: .labels, markdown)
|
||||
return nil
|
||||
}
|
||||
return .init(icon: icon, value: parts[1])
|
||||
}
|
||||
return ContentLabels(labels: labels).content
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user