real gifs!!

This commit is contained in:
neon443
2025-11-20 21:23:32 +00:00
parent ccadff053e
commit 5b0d6ab9ff
3 changed files with 68 additions and 39 deletions

View File

@@ -6,7 +6,37 @@
// //
import Foundation import Foundation
import UIKit
class GifManager { class GifManager {
static let defaultDuration: Double = 0.083333333333333329
static func gifFrom(url: URL) -> [(frame: CGImage, showFor: Double)] {
// let url = URL(string: "https://emoji.slack-edge.com/T0266FRGM/yay-bounce/046cfcc7ed81030f.gif")!
// guard let source = CGImageSourceCreateWithURL(url as CFURL, nil) else { fatalError("couldnt create source") }
guard let data = try? Data(contentsOf: url) else { return [] }
return gifFrom(data: data)
}
static func gifFrom(data: Data) -> [(frame: CGImage, showFor: Double)] {
guard let source = CGImageSourceCreateWithData(data as NSData, nil) else { fatalError("couldnt create source") }
let frameCount = CGImageSourceGetCount(source)
var result: [(frame: CGImage, showFor: Double)] = []
for i in 0..<frameCount {
guard let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) else {
print("AAAA")
continue
}
if let properties = CGImageSourceCopyPropertiesAtIndex(source, i, nil),
let gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary,
let frameDuration = (gifInfo[kCGImagePropertyGIFDelayTime as String] as? NSNumber) {
result.append((cgImage, frameDuration.doubleValue))
} else {
result.append((cgImage, defaultDuration))
}
}
return result
}
} }

View File

@@ -10,24 +10,44 @@ import UIKit
import SwiftUI import SwiftUI
import WebKit import WebKit
struct GifView: UIViewRepresentable { struct GifView: View {
private let url: URL @State var url: URL
@State var gif: [(frame: CGImage, showFor: Double)] = []
@State var currentI: Int = 0
@State var go: Bool = false
init(url: URL) { var body: some View {
self.url = url // /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Hello, world!@*/Text("Hello, world!")/*@END_MENU_TOKEN@*/
} TimelineView(.animation) { tl in
VStack {
func makeUIView(context: Context) -> WKWebView { if currentI < gif.count {
let webview = WKWebView() let image = Image(uiImage: .init(cgImage: gif[currentI].frame))
image
webview.allowsLinkPreview = false .resizable().scaledToFit()
webview.allowsBackForwardNavigationGestures = false }
}
webview.load(URLRequest(url: url)) }
return webview .onChange(of: go) { _ in
} if currentI == (gif.count-1) {
currentI = 0
func updateUIView(_ uiView: WKWebView, context: Context) { } else {
uiView.reload() currentI += 1
}
DispatchQueue.main.asyncAfter(deadline: .now()+gif[currentI].showFor) {
go.toggle()
}
}
.onAppear {
self.gif = GifManager.gifFrom(url: url)
DispatchQueue.main.asyncAfter(deadline: .now()+gif[0].showFor) {
go.toggle()
}
}
} }
} }
#Preview {
GifView(
url: URL(string: "https://files.catbox.moe/3x5sea.gif")!
)
}

View File

@@ -23,14 +23,6 @@ struct EmojiPreview: View {
if let image = emoji.image { if let image = emoji.image {
if emoji.localImageURLString.contains(".gif") { if emoji.localImageURLString.contains(".gif") {
GifView(url: emoji.localImageURL) GifView(url: emoji.localImageURL)
// if let gifImage {
// gifImage
// .resizable().scaledToFit()
// } else {
// Text("uhhhh")
// .foregroundStyle(.red)
// .font(.largeTitle)
// }
} else { } else {
Image(uiImage: image) Image(uiImage: image)
.resizable().scaledToFit() .resizable().scaledToFit()
@@ -58,19 +50,6 @@ struct EmojiPreview: View {
} }
} }
} }
// .onAppear {
// guard emoji.localImageURLString.contains(".gif") else { return }
// gifImage = nil
// guard let gifData = try? Data(contentsOf: emoji.localImageURL) as CFData else { return }
// CGAnimateImageDataWithBlock(gifData, nil) { index, cgImage, stop in
// if stopPointer != stop {
// stopPointer?.pointee.toggle()
// stopPointer = stop
// }
// guard !stop.pointee else { return }
// gifImage = Image(uiImage: .init(cgImage: cgImage))
// }
// }
.id(id) .id(id)
} }
} }