mirror of
https://github.com/neon443/StickerSlack.git
synced 2026-03-11 05:19:13 +00:00
updated downloadImage()
- to use cached local version if available - now writes to disk if not already saved rewrote toEmojis() just a simple map of ApiEmoji($0).toEmoji() use the new toEmojis in emojiHoarder now the emojiDB gets stored locally, need to make it fetch it if it can cos cache cant be valid forever yk using neon443/Haptics for haptics lol added a download button on EmojiPreview, if downloaded a lil download icon shows up, and will show that one instead of AsyncImage
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
A924C3722EA9127200F20781 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A924C3712EA9127200F20781 /* Emoji.swift */; };
|
A924C3722EA9127200F20781 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A924C3712EA9127200F20781 /* Emoji.swift */; };
|
||||||
A924C3732EA9127200F20781 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A924C3712EA9127200F20781 /* Emoji.swift */; };
|
A924C3732EA9127200F20781 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A924C3712EA9127200F20781 /* Emoji.swift */; };
|
||||||
|
A924C3782EA9225800F20781 /* Haptics in Frameworks */ = {isa = PBXBuildFile; productRef = A924C3772EA9225800F20781 /* Haptics */; };
|
||||||
A940FE3D2EA232590016870B /* ApiEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A940FE3C2EA232590016870B /* ApiEmoji.swift */; };
|
A940FE3D2EA232590016870B /* ApiEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = A940FE3C2EA232590016870B /* ApiEmoji.swift */; };
|
||||||
A949B1F32EA04E8200215164 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A949B1EF2EA04E8200215164 /* Assets.xcassets */; };
|
A949B1F32EA04E8200215164 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A949B1EF2EA04E8200215164 /* Assets.xcassets */; };
|
||||||
A949B1F42EA04E8200215164 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949B1F02EA04E8200215164 /* ContentView.swift */; };
|
A949B1F42EA04E8200215164 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949B1F02EA04E8200215164 /* ContentView.swift */; };
|
||||||
@@ -77,6 +78,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
A924C3782EA9225800F20781 /* Haptics in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -190,6 +192,7 @@
|
|||||||
);
|
);
|
||||||
name = StickerSlack;
|
name = StickerSlack;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
A924C3772EA9225800F20781 /* Haptics */,
|
||||||
);
|
);
|
||||||
productName = StickerSlack;
|
productName = StickerSlack;
|
||||||
productReference = A949B1DF2EA04C0B00215164 /* StickerSlack.app */;
|
productReference = A949B1DF2EA04C0B00215164 /* StickerSlack.app */;
|
||||||
@@ -241,6 +244,9 @@
|
|||||||
);
|
);
|
||||||
mainGroup = A949B1D62EA04C0B00215164;
|
mainGroup = A949B1D62EA04C0B00215164;
|
||||||
minimizedProjectReferenceProxies = 1;
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
packageReferences = (
|
||||||
|
A924C3762EA9225800F20781 /* XCLocalSwiftPackageReference "../Haptics" */,
|
||||||
|
);
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = A949B1E02EA04C0B00215164 /* Products */;
|
productRefGroup = A949B1E02EA04C0B00215164 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -624,6 +630,20 @@
|
|||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
|
/* Begin XCLocalSwiftPackageReference section */
|
||||||
|
A924C3762EA9225800F20781 /* XCLocalSwiftPackageReference "../Haptics" */ = {
|
||||||
|
isa = XCLocalSwiftPackageReference;
|
||||||
|
relativePath = ../Haptics;
|
||||||
|
};
|
||||||
|
/* End XCLocalSwiftPackageReference section */
|
||||||
|
|
||||||
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
A924C3772EA9225800F20781 /* Haptics */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Haptics;
|
||||||
|
};
|
||||||
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = A949B1D72EA04C0B00215164 /* Project object */;
|
rootObject = A949B1D72EA04C0B00215164 /* Project object */;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ struct Emoji: Codable, Identifiable, Hashable {
|
|||||||
self.remoteImageURL = apiEmoji.url
|
self.remoteImageURL = apiEmoji.url
|
||||||
self.localImageURL = EmojiHoarder.container.appendingPathComponent(id.uuidString, conformingTo: .image)
|
self.localImageURL = EmojiHoarder.container.appendingPathComponent(id.uuidString, conformingTo: .image)
|
||||||
|
|
||||||
|
|
||||||
// Task { [weak self] in
|
// Task { [weak self] in
|
||||||
// let (data, response) = try await URLSession.shared.data(from: apiEmoji.url)
|
// let (data, response) = try await URLSession.shared.data(from: apiEmoji.url)
|
||||||
// self.image = UIImage(data: data)
|
// self.image = UIImage(data: data)
|
||||||
@@ -58,8 +57,13 @@ struct Emoji: Codable, Identifiable, Hashable {
|
|||||||
// self.image = UIImage(data: image) ?? UIImage()
|
// self.image = UIImage(data: image) ?? UIImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadImage() async throws -> UIImage {
|
func downloadImage() async throws -> UIImage {
|
||||||
|
if let data = try? Data(contentsOf: localImageURL),
|
||||||
|
let uiimage = UIImage(data: data) {
|
||||||
|
return uiimage
|
||||||
|
}
|
||||||
let (data, _) = try await URLSession.shared.data(from: remoteImageURL)
|
let (data, _) = try await URLSession.shared.data(from: remoteImageURL)
|
||||||
|
try! data.write(to: localImageURL)
|
||||||
return UIImage(data: data)!
|
return UIImage(data: data)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,20 +12,8 @@ struct SlackResponse: Codable {
|
|||||||
var imageUrl: String
|
var imageUrl: String
|
||||||
var alias: String?
|
var alias: String?
|
||||||
|
|
||||||
// func toEmojis() -> [Emoji] {
|
|
||||||
// let initialMap = emoji.map {
|
static func toEmojis(from: [SlackResponse]) -> [Emoji] {
|
||||||
// Emoji(name: $0.key, url: $0.value)
|
return from.map { ApiEmoji(name: $0.name, url: $0.imageUrl).toEmoji() }
|
||||||
// }
|
}
|
||||||
// return initialMap.map {
|
|
||||||
// var ret = $0
|
|
||||||
// if ret.urlString.prefix(6) == "alias:" {
|
|
||||||
// if let orig = initialMap.first(where: {
|
|
||||||
// $0.name == "\(ret.urlString.dropFirst(6))"
|
|
||||||
// }) {
|
|
||||||
// ret.urlString = orig.urlString
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return ret
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,22 +8,28 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
class EmojiHoarder: ObservableObject {
|
class EmojiHoarder: ObservableObject {
|
||||||
static let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.neon443.StickerSlack")!
|
static let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.neon443.StickerSlack")!.appendingPathComponent("Library", conformingTo: .directory)
|
||||||
|
static let localEmojiDB: URL = EmojiHoarder.container.appendingPathExtension("localEmojiDB.json")
|
||||||
private let endpoint: URL = URL(string: "https://cachet.dunkirk.sh/emojis")!
|
private let endpoint: URL = URL(string: "https://cachet.dunkirk.sh/emojis")!
|
||||||
|
|
||||||
@Published var emojis: [Emoji]
|
@Published var emojis: [Emoji]
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
if let localEmojiDB = try? Data(contentsOf: EmojiHoarder.localEmojiDB) {
|
||||||
|
let decoded = try! JSONDecoder().decode([Emoji].self, from: localEmojiDB)
|
||||||
|
self.emojis = decoded
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard let data = try? Data(contentsOf: endpoint) else { fatalError("cachet unreachable") }
|
guard let data = try? Data(contentsOf: endpoint) else { fatalError("cachet unreachable") }
|
||||||
|
|
||||||
let decoded: [SlackResponse] = try! JSONDecoder().decode([SlackResponse].self, from: data)
|
let decoded: [SlackResponse] = try! JSONDecoder().decode([SlackResponse].self, from: data)
|
||||||
self.emojis = decoded.map { ApiEmoji(name: $0.name, url: $0.imageUrl).toEmoji() }
|
self.emojis = SlackResponse.toEmojis(from: decoded)
|
||||||
// Task {
|
|
||||||
// for i in emojis.indices {
|
try! JSONEncoder().encode(emojis).write(to: EmojiHoarder.localEmojiDB)
|
||||||
// emojis[i].image = try? await emojis[i].loadImage()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func storeStickers
|
// func storeStickers
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import Haptics
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@StateObject var hoarder: EmojiHoarder = EmojiHoarder()
|
@StateObject var hoarder: EmojiHoarder = EmojiHoarder()
|
||||||
@@ -15,8 +16,18 @@ struct ContentView: View {
|
|||||||
TabView {
|
TabView {
|
||||||
List {
|
List {
|
||||||
ForEach(hoarder.emojis, id: \.self) { emoji in
|
ForEach(hoarder.emojis, id: \.self) { emoji in
|
||||||
EmojiPreview(emoji: emoji)
|
HStack {
|
||||||
.frame(maxWidth: 100)
|
EmojiPreview(emoji: emoji)
|
||||||
|
.frame(maxWidth: 100)
|
||||||
|
Spacer()
|
||||||
|
Button("", systemImage: "arrow.down.circle") {
|
||||||
|
Task {
|
||||||
|
let _ = try? await emoji.downloadImage()
|
||||||
|
Haptic.success.trigger()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tabItem {
|
.tabItem {
|
||||||
|
|||||||
@@ -6,34 +6,55 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import Haptics
|
||||||
|
|
||||||
struct EmojiPreview: View {
|
struct EmojiPreview: View {
|
||||||
@State var emoji: Emoji
|
@State var emoji: Emoji
|
||||||
|
|
||||||
@State private var id: UUID = UUID()
|
@State private var id: UUID = UUID()
|
||||||
|
@State private var image: UIImage?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Text(emoji.name)
|
Text(emoji.name)
|
||||||
if let image = emoji.image {
|
|
||||||
Image(uiImage: image)
|
Group {
|
||||||
} else {
|
if let localImage = try? Data(contentsOf: emoji.localImageURL),
|
||||||
ProgressView()
|
let image = UIImage(data: localImage) {
|
||||||
}
|
Image(uiImage: image)
|
||||||
AsyncImage(url: emoji.remoteImageURL) { phase in
|
|
||||||
if let image = phase.image {
|
|
||||||
image
|
|
||||||
.resizable().scaledToFit()
|
.resizable().scaledToFit()
|
||||||
} else if phase.error != nil {
|
.border(.orange)
|
||||||
Image(systemName: "xmark.app.fill")
|
.overlay(alignment: .bottomLeading) {
|
||||||
.resizable().scaledToFit()
|
Image(systemName: "arrow.down.circle.fill")
|
||||||
.symbolRenderingMode(.hierarchical)
|
.resizable().scaledToFit()
|
||||||
.foregroundStyle(.red)
|
.frame(width: 20, height: 20)
|
||||||
.onTapGesture {
|
.symbolRenderingMode(.hierarchical)
|
||||||
id = UUID()
|
// .foregroundStyle(.gray)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ProgressView()
|
AsyncImage(url: emoji.remoteImageURL) { phase in
|
||||||
|
if let image = phase.image {
|
||||||
|
image
|
||||||
|
.resizable().scaledToFit()
|
||||||
|
} else if phase.error != nil {
|
||||||
|
Image(systemName: "xmark.app.fill")
|
||||||
|
.resizable().scaledToFit()
|
||||||
|
.padding()
|
||||||
|
.symbolRenderingMode(.hierarchical)
|
||||||
|
.foregroundStyle(.red)
|
||||||
|
.onTapGesture {
|
||||||
|
id = UUID()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ProgressView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
Task {
|
||||||
|
image = try? await emoji.downloadImage()
|
||||||
|
Haptic.success.trigger()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.id(id)
|
.id(id)
|
||||||
|
|||||||
Reference in New Issue
Block a user