Add screen slider component
This commit is contained in:
parent
a8bc7298ff
commit
d4c0da0a32
@ -180,6 +180,8 @@
|
|||||||
E2B4821A2D63AFF6005C309D /* NotificationSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B482192D63AFEE005C309D /* NotificationSender.swift */; };
|
E2B4821A2D63AFF6005C309D /* NotificationSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B482192D63AFEE005C309D /* NotificationSender.swift */; };
|
||||||
E2B4821C2D63B062005C309D /* NotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B4821B2D63B05B005C309D /* NotificationRequest.swift */; };
|
E2B4821C2D63B062005C309D /* NotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B4821B2D63B05B005C309D /* NotificationRequest.swift */; };
|
||||||
E2B4821E2D63B096005C309D /* WebNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B4821D2D63B096005C309D /* WebNotification.swift */; };
|
E2B4821E2D63B096005C309D /* WebNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B4821D2D63B096005C309D /* WebNotification.swift */; };
|
||||||
|
E2B482202D670753005C309D /* WallpaperSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B4821F2D67074C005C309D /* WallpaperSlider.swift */; };
|
||||||
|
E2B482222D676BF7005C309D /* PhoneScreensBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B482212D676BEB005C309D /* PhoneScreensBlock.swift */; };
|
||||||
E2B85F362C426BEE0047CD0C /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = E2B85F352C426BEE0047CD0C /* SFSafeSymbols */; };
|
E2B85F362C426BEE0047CD0C /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = E2B85F352C426BEE0047CD0C /* SFSafeSymbols */; };
|
||||||
E2B85F3B2C428F0E0047CD0C /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B85F3A2C428F0D0047CD0C /* Post.swift */; };
|
E2B85F3B2C428F0E0047CD0C /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B85F3A2C428F0D0047CD0C /* Post.swift */; };
|
||||||
E2B85F3D2C4293F80047CD0C /* FeedPageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B85F3C2C4293F80047CD0C /* FeedPageGenerator.swift */; };
|
E2B85F3D2C4293F80047CD0C /* FeedPageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B85F3C2C4293F80047CD0C /* FeedPageGenerator.swift */; };
|
||||||
@ -447,6 +449,8 @@
|
|||||||
E2B482192D63AFEE005C309D /* NotificationSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSender.swift; sourceTree = "<group>"; };
|
E2B482192D63AFEE005C309D /* NotificationSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSender.swift; sourceTree = "<group>"; };
|
||||||
E2B4821B2D63B05B005C309D /* NotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRequest.swift; sourceTree = "<group>"; };
|
E2B4821B2D63B05B005C309D /* NotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRequest.swift; sourceTree = "<group>"; };
|
||||||
E2B4821D2D63B096005C309D /* WebNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebNotification.swift; sourceTree = "<group>"; };
|
E2B4821D2D63B096005C309D /* WebNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebNotification.swift; sourceTree = "<group>"; };
|
||||||
|
E2B4821F2D67074C005C309D /* WallpaperSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperSlider.swift; sourceTree = "<group>"; };
|
||||||
|
E2B482212D676BEB005C309D /* PhoneScreensBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneScreensBlock.swift; sourceTree = "<group>"; };
|
||||||
E2B85F3A2C428F0D0047CD0C /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
|
E2B85F3A2C428F0D0047CD0C /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
|
||||||
E2B85F3C2C4293F80047CD0C /* FeedPageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedPageGenerator.swift; sourceTree = "<group>"; };
|
E2B85F3C2C4293F80047CD0C /* FeedPageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedPageGenerator.swift; sourceTree = "<group>"; };
|
||||||
E2B85F402C4294790047CD0C /* PageHead.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageHead.swift; sourceTree = "<group>"; };
|
E2B85F402C4294790047CD0C /* PageHead.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageHead.swift; sourceTree = "<group>"; };
|
||||||
@ -690,6 +694,7 @@
|
|||||||
E29D311E2D0320D90051B7F4 /* ContentElements */ = {
|
E29D311E2D0320D90051B7F4 /* ContentElements */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E2B4821F2D67074C005C309D /* WallpaperSlider.swift */,
|
||||||
E29D31C12D0DBED70051B7F4 /* AudioPlayer */,
|
E29D31C12D0DBED70051B7F4 /* AudioPlayer */,
|
||||||
E29D318A2D0B07E60051B7F4 /* ContentBox.swift */,
|
E29D318A2D0B07E60051B7F4 /* ContentBox.swift */,
|
||||||
E29D31212D0363FA0051B7F4 /* ContentButtons.swift */,
|
E29D31212D0363FA0051B7F4 /* ContentButtons.swift */,
|
||||||
@ -1103,6 +1108,7 @@
|
|||||||
E2FE0F342D2B27E6002963B7 /* Blocks */ = {
|
E2FE0F342D2B27E6002963B7 /* Blocks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E2B482212D676BEB005C309D /* PhoneScreensBlock.swift */,
|
||||||
E2FE0F652D2C3B33002963B7 /* LabelsBlock.swift */,
|
E2FE0F652D2C3B33002963B7 /* LabelsBlock.swift */,
|
||||||
E2FE0F5C2D2BD006002963B7 /* Types */,
|
E2FE0F5C2D2BD006002963B7 /* Types */,
|
||||||
E2FE0F322D2B265F002963B7 /* AudioBlock.swift */,
|
E2FE0F322D2B265F002963B7 /* AudioBlock.swift */,
|
||||||
@ -1328,6 +1334,7 @@
|
|||||||
E29D31942D0B7D280051B7F4 /* SimpleImage.swift in Sources */,
|
E29D31942D0B7D280051B7F4 /* SimpleImage.swift in Sources */,
|
||||||
E29D31632D06E95D0051B7F4 /* NavigationIcon.swift in Sources */,
|
E29D31632D06E95D0051B7F4 /* NavigationIcon.swift in Sources */,
|
||||||
E2FE0F362D2B27F9002963B7 /* BlockProcessor.swift in Sources */,
|
E2FE0F362D2B27F9002963B7 /* BlockProcessor.swift in Sources */,
|
||||||
|
E2B482222D676BF7005C309D /* PhoneScreensBlock.swift in Sources */,
|
||||||
E2FD1D1B2D2DC63800B48627 /* LinkPreviewDetailView.swift in Sources */,
|
E2FD1D1B2D2DC63800B48627 /* LinkPreviewDetailView.swift in Sources */,
|
||||||
E22990462D10B7A7009F8D77 /* SecurityScopeStatus.swift in Sources */,
|
E22990462D10B7A7009F8D77 /* SecurityScopeStatus.swift in Sources */,
|
||||||
E29D31512D06168E0051B7F4 /* PostListView.swift in Sources */,
|
E29D31512D06168E0051B7F4 /* PostListView.swift in Sources */,
|
||||||
@ -1343,6 +1350,7 @@
|
|||||||
E21850092CEE01C30090B18B /* PagePickerView.swift in Sources */,
|
E21850092CEE01C30090B18B /* PagePickerView.swift in Sources */,
|
||||||
E29D31492D0489BB0051B7F4 /* AddFileView.swift in Sources */,
|
E29D31492D0489BB0051B7F4 /* AddFileView.swift in Sources */,
|
||||||
E2A21C2A2CB2AA4F0060935B /* Post+Mock.swift in Sources */,
|
E2A21C2A2CB2AA4F0060935B /* Post+Mock.swift in Sources */,
|
||||||
|
E2B482202D670753005C309D /* WallpaperSlider.swift in Sources */,
|
||||||
E29D312E2D03A0D70051B7F4 /* LocalizedPageDetailView.swift in Sources */,
|
E29D312E2D03A0D70051B7F4 /* LocalizedPageDetailView.swift in Sources */,
|
||||||
E2581DED2C75202400F1F079 /* Tag.swift in Sources */,
|
E2581DED2C75202400F1F079 /* Tag.swift in Sources */,
|
||||||
E29D31302D03A2C50051B7F4 /* DescriptionField.swift in Sources */,
|
E29D31302D03A2C50051B7F4 /* DescriptionField.swift in Sources */,
|
||||||
|
@ -13,6 +13,8 @@ enum ContentBlock: String, CaseIterable {
|
|||||||
|
|
||||||
case labels
|
case labels
|
||||||
|
|
||||||
|
case screens
|
||||||
|
|
||||||
var processor: BlockProcessor.Type {
|
var processor: BlockProcessor.Type {
|
||||||
switch self {
|
switch self {
|
||||||
case .audio: return AudioBlock.self
|
case .audio: return AudioBlock.self
|
||||||
@ -21,6 +23,7 @@ enum ContentBlock: String, CaseIterable {
|
|||||||
case .button: return ButtonBlock.self
|
case .button: return ButtonBlock.self
|
||||||
case .buttons: return ButtonsBlock.self
|
case .buttons: return ButtonsBlock.self
|
||||||
case .labels: return LabelsBlock.self
|
case .labels: return LabelsBlock.self
|
||||||
|
case .screens: return PhoneScreensBlock.self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
104
CHDataManagement/Generator/Blocks/PhoneScreensBlock.swift
Normal file
104
CHDataManagement/Generator/Blocks/PhoneScreensBlock.swift
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
struct PhoneScreensBlock: OrderedKeyBlockProcessor {
|
||||||
|
|
||||||
|
enum Key: String {
|
||||||
|
case id
|
||||||
|
case frame
|
||||||
|
case tall
|
||||||
|
case wide
|
||||||
|
}
|
||||||
|
|
||||||
|
static let blockId: ContentBlock = .screens
|
||||||
|
|
||||||
|
let content: Content
|
||||||
|
|
||||||
|
let results: PageGenerationResults
|
||||||
|
|
||||||
|
let language: ContentLanguage
|
||||||
|
|
||||||
|
init(content: Content, results: PageGenerationResults, language: ContentLanguage) {
|
||||||
|
self.content = content
|
||||||
|
self.results = results
|
||||||
|
self.language = language
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(_ arguments: [(key: Key, value: String)], markdown: Substring) -> String {
|
||||||
|
print("Processing Phone Screens Block")
|
||||||
|
guard let frameId = arguments.first(where: {$0.key == .frame })?.value else {
|
||||||
|
invalid(markdown)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
guard let frameFile = content.file(frameId) else {
|
||||||
|
results.missing(file: frameId, source: "Wallpaper Block")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let id = arguments.first(where: {$0.key == .id })?.value else {
|
||||||
|
invalid(markdown)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining = arguments.filter { $0.key == .tall || $0.key == .wide }
|
||||||
|
|
||||||
|
var images = [WallpaperSlider.Image]()
|
||||||
|
var tall: FileResource?
|
||||||
|
var wide: FileResource?
|
||||||
|
for (key, fileId) in remaining {
|
||||||
|
guard let file = content.file(fileId) else {
|
||||||
|
print("Missing file: \(fileId)")
|
||||||
|
results.missing(file: fileId, source: "Wallpaper Block")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if key == .tall {
|
||||||
|
if tall != nil {
|
||||||
|
print("Another tall image: \(file.id)")
|
||||||
|
invalid(markdown)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if let other = wide {
|
||||||
|
let image = WallpaperSlider.Image(
|
||||||
|
tall: file,
|
||||||
|
wide: other,
|
||||||
|
language: language,
|
||||||
|
results: results)
|
||||||
|
images.append(image)
|
||||||
|
wide = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tall = file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// key == .wide
|
||||||
|
if wide != nil {
|
||||||
|
print("Another wide image: \(file.id)")
|
||||||
|
invalid(markdown)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
guard let other = tall else {
|
||||||
|
wide = file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let image = WallpaperSlider.Image(
|
||||||
|
tall: other,
|
||||||
|
wide: file,
|
||||||
|
language: language,
|
||||||
|
results: results)
|
||||||
|
images.append(image)
|
||||||
|
tall = nil
|
||||||
|
}
|
||||||
|
if tall != nil || wide != nil {
|
||||||
|
invalid(markdown)
|
||||||
|
print("Wide/tall does not have the same number of items")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let frame = WallpaperSlider.Frame(frame: frameFile, language: language, results: results)
|
||||||
|
let slider = WallpaperSlider(frame: frame, images: images, id: id)
|
||||||
|
|
||||||
|
results.require(footer: slider.script)
|
||||||
|
results.require(headers: .swiperJs, .swiperCss)
|
||||||
|
results.require(header: .style(slider.style))
|
||||||
|
|
||||||
|
return slider.content
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,8 @@ enum HeaderElement {
|
|||||||
|
|
||||||
case manifest(FileResource)
|
case manifest(FileResource)
|
||||||
|
|
||||||
|
case style(String)
|
||||||
|
|
||||||
var order: Int {
|
var order: Int {
|
||||||
switch self {
|
switch self {
|
||||||
case .charset: 1
|
case .charset: 1
|
||||||
@ -69,6 +71,7 @@ enum HeaderElement {
|
|||||||
case .ogDescription: 104
|
case .ogDescription: 104
|
||||||
case .ogImage: 105
|
case .ogImage: 105
|
||||||
case .ogUrl: 106
|
case .ogUrl: 106
|
||||||
|
case .style: 200
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +139,8 @@ extension HeaderElement {
|
|||||||
return "<meta name='robots' content='noindex'>"
|
return "<meta name='robots' content='noindex'>"
|
||||||
case .manifest(let file):
|
case .manifest(let file):
|
||||||
return "<link rel='manifest' href='\(file.absoluteUrl)'>"
|
return "<link rel='manifest' href='\(file.absoluteUrl)'>"
|
||||||
|
case .style(let style):
|
||||||
|
return "<style>\(style)</style>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,6 +179,8 @@ extension HeaderElement: CustomStringConvertible {
|
|||||||
return "robots"
|
return "robots"
|
||||||
case .manifest:
|
case .manifest:
|
||||||
return "manifest"
|
return "manifest"
|
||||||
|
case .style:
|
||||||
|
return "style"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
|
|
||||||
enum KnownHeaderElement: Int {
|
enum KnownHeaderElement {
|
||||||
|
|
||||||
case codeHightlighting = 4
|
case codeHightlighting
|
||||||
|
|
||||||
case modelViewer = 3
|
case modelViewer
|
||||||
|
|
||||||
/// CSS File to style the audio player
|
/// CSS File to style the audio player
|
||||||
case audioPlayerCss = 1
|
case audioPlayerCss
|
||||||
|
|
||||||
/// JavaScript file for the audio player
|
/// JavaScript file for the audio player
|
||||||
case audioPlayerJs = 2
|
case audioPlayerJs
|
||||||
|
|
||||||
case imageCompareJs = 5
|
case imageCompareJs
|
||||||
|
|
||||||
case imageCompareCss = 6
|
case imageCompareCss
|
||||||
|
|
||||||
|
case swiperCss
|
||||||
|
|
||||||
|
case swiperJs
|
||||||
|
|
||||||
|
case style(String)
|
||||||
|
|
||||||
func header(content: Content) -> HeaderElement? {
|
func header(content: Content) -> HeaderElement? {
|
||||||
switch self {
|
switch self {
|
||||||
@ -41,15 +47,32 @@ enum KnownHeaderElement: Int {
|
|||||||
if let file = content.settings.pages.imageCompareCssFile {
|
if let file = content.settings.pages.imageCompareCssFile {
|
||||||
return .css(file: file, order: HeaderElement.imageCompareCssOrder)
|
return .css(file: file, order: HeaderElement.imageCompareCssOrder)
|
||||||
}
|
}
|
||||||
|
case .swiperCss:
|
||||||
|
if let swiperCss = content.settings.posts.swiperCssFile {
|
||||||
|
return .css(file: swiperCss, order: HeaderElement.swiperCssFileOrder)
|
||||||
|
}
|
||||||
|
case .swiperJs:
|
||||||
|
if let swiperJs = content.settings.posts.swiperJsFile {
|
||||||
|
return .js(file: swiperJs, defer: true)
|
||||||
|
}
|
||||||
|
case .style(let code):
|
||||||
|
return .style(code)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension KnownHeaderElement: Comparable {
|
extension KnownHeaderElement: Equatable {
|
||||||
|
|
||||||
static func < (lhs: KnownHeaderElement, rhs: KnownHeaderElement) -> Bool {
|
static func == (lhs: KnownHeaderElement, rhs: KnownHeaderElement) -> Bool {
|
||||||
lhs.rawValue < rhs.rawValue
|
lhs.description == rhs.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension KnownHeaderElement: Hashable {
|
||||||
|
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +92,12 @@ extension KnownHeaderElement: CustomStringConvertible {
|
|||||||
return "image-compare-js"
|
return "image-compare-js"
|
||||||
case .imageCompareCss:
|
case .imageCompareCss:
|
||||||
return "image-compare-css"
|
return "image-compare-css"
|
||||||
|
case .swiperCss:
|
||||||
|
return "swiper-css"
|
||||||
|
case .swiperJs:
|
||||||
|
return "swiper-js"
|
||||||
|
case .style(let style):
|
||||||
|
return "style: " + style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
struct WallpaperSlider: HtmlProducer {
|
||||||
|
|
||||||
|
static let frameHeight = 585
|
||||||
|
|
||||||
|
static let frameWidth = 270
|
||||||
|
|
||||||
|
static let imageWidth = 250
|
||||||
|
|
||||||
|
static let imageHeight = 500
|
||||||
|
|
||||||
|
let frame: Frame
|
||||||
|
|
||||||
|
let images: [Image]
|
||||||
|
|
||||||
|
let id: String
|
||||||
|
|
||||||
|
struct Frame {
|
||||||
|
|
||||||
|
let alt: String
|
||||||
|
|
||||||
|
let x1: ImageVersion
|
||||||
|
|
||||||
|
let x2: ImageVersion
|
||||||
|
|
||||||
|
init(frame: FileResource, language: ContentLanguage, results: PageGenerationResults) {
|
||||||
|
self.x1 = frame.imageVersion(
|
||||||
|
width: WallpaperSlider.frameWidth * 2,
|
||||||
|
height: WallpaperSlider.frameHeight * 2,
|
||||||
|
type: frame.type)
|
||||||
|
|
||||||
|
self.x2 = frame.imageVersion(
|
||||||
|
width: WallpaperSlider.frameWidth * 2,
|
||||||
|
height: WallpaperSlider.frameHeight * 2,
|
||||||
|
type: frame.type)
|
||||||
|
|
||||||
|
self.alt = frame.localized(in: language) ?? "A frame"
|
||||||
|
|
||||||
|
results.require(image: x1)
|
||||||
|
results.require(image: x2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Image {
|
||||||
|
|
||||||
|
let display: ImageSet
|
||||||
|
|
||||||
|
let wide: DownloadImage
|
||||||
|
|
||||||
|
let tall: DownloadImage
|
||||||
|
|
||||||
|
struct DownloadImage {
|
||||||
|
|
||||||
|
let url: String
|
||||||
|
|
||||||
|
let button: String
|
||||||
|
}
|
||||||
|
|
||||||
|
init(tall: FileResource, wide: FileResource, language: ContentLanguage, results: PageGenerationResults) {
|
||||||
|
self.display = tall.imageSet(
|
||||||
|
width: WallpaperSlider.imageWidth,
|
||||||
|
height: WallpaperSlider.imageHeight,
|
||||||
|
language: language)
|
||||||
|
let wideButton = language == .english ? "Wide" : "Breit"
|
||||||
|
self.wide = .init(url: wide.absoluteUrl, button: wideButton)
|
||||||
|
|
||||||
|
let tallButton = language == .english ? "Tall" : "Hoch"
|
||||||
|
self.tall = .init(url: tall.absoluteUrl, button: tallButton)
|
||||||
|
|
||||||
|
results.require(imageSet: display)
|
||||||
|
results.require(file: wide)
|
||||||
|
results.require(file: tall)
|
||||||
|
results.require(icon: .buttonDownload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func populate(_ result: inout String) {
|
||||||
|
let icon: PageIcon = .buttonDownload
|
||||||
|
|
||||||
|
result += "<div class='swiper-container'>"
|
||||||
|
result += "<img class='overlay-image' srcset='\(frame.x2.outputPath) 2x' src='\(frame.x1.outputPath)' \(frame.alt)/>"
|
||||||
|
result += "<div id='wallpaper-\(id)' class='swiper'><div class='swiper-wrapper'>"
|
||||||
|
for image in images {
|
||||||
|
result += "<div class='swiper-slide'>"
|
||||||
|
image.display.populate(&result)
|
||||||
|
result += "<div class='button-container'>"
|
||||||
|
result += "<a class='tag custom-button' href='\(image.tall.url)' download>\(icon.usageString)\(image.tall.button)</a>"
|
||||||
|
result += "<a class='tag custom-button' href='\(image.wide.url)' download>\(icon.usageString)\(image.wide.button)</a>"
|
||||||
|
result += "</div></div>" // Close button-container, swiper-slide
|
||||||
|
}
|
||||||
|
result += "</div>" // Close swiper-wrapper
|
||||||
|
result += "<div class='swiper-button-next'></div>"
|
||||||
|
result += "<div class='swiper-button-prev'></div>"
|
||||||
|
result += "</div>" // Close swiper
|
||||||
|
result += "</div>" // Close swiper-container
|
||||||
|
}
|
||||||
|
|
||||||
|
var style: String {
|
||||||
|
"""
|
||||||
|
.swiper {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.swiper-container {
|
||||||
|
position: relative;
|
||||||
|
max-width: 250px;
|
||||||
|
max-height: 500px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 40px;
|
||||||
|
aspect-ratio: 1 / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-image {
|
||||||
|
position: absolute;
|
||||||
|
top: -8.5%;
|
||||||
|
left: -4%;
|
||||||
|
width: 108%;
|
||||||
|
height: 117%;
|
||||||
|
z-index: 10;
|
||||||
|
object-fit: contain;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.button-container {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 15%;
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
.custom-button {
|
||||||
|
padding: 10px 10px;
|
||||||
|
width: 60px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: rgba(29, 29, 29, 0.74);
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 12px;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
.swiper-button-next {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.swiper-button-prev {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
var script: String {
|
||||||
|
"""
|
||||||
|
<script>
|
||||||
|
window.onload = () => {
|
||||||
|
var swiper_\(id) = new Swiper("#wallpaper-\(id)", {
|
||||||
|
loop: true,
|
||||||
|
navigation: {
|
||||||
|
nextEl: ".swiper-button-next",
|
||||||
|
prevEl: ".swiper-button-prev",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user