-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds a gif keyboard, kind of, to the posting view. Leverages the nostr build API to get latest gifs. Changelog-Added: Nostr Build GIF keyboard Signed-off-by: ericholguin <[email protected]>
- Loading branch information
1 parent
49c8d63
commit 2a4f411
Showing
6 changed files
with
264 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "nb-logo_nb-logo-color.svg", | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
damus/Assets.xcassets/nostrbuild.imageset/nb-logo_nb-logo-color.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,43 @@ | ||
// | ||
// NostrBuildGIF.swift | ||
// damus | ||
// | ||
// Created by eric on 8/14/24. | ||
// | ||
|
||
import Foundation | ||
|
||
func makeGIFRequest(cursor: Int) async throws -> NostrBuildGIFResponse { | ||
var request = URLRequest(url: URL(string: String(format: "https://nostr.build/api/v2/gifs/get?cursor=%d&limit=%d&random=%d", | ||
cursor, | ||
30, | ||
0))!) | ||
|
||
request.httpMethod = "GET" | ||
request.setValue("application/json", forHTTPHeaderField: "Content-Type") | ||
|
||
let response: NostrBuildGIFResponse = try await decodedData(for: request) | ||
return response | ||
} | ||
|
||
private func decodedData<Output: Decodable>(for request: URLRequest) async throws -> Output { | ||
let decoder = JSONDecoder() | ||
let session = URLSession.shared | ||
let (data, _) = try await session.data(for: request) | ||
let result = try decoder.decode(Output.self, from: data) | ||
return result | ||
} | ||
|
||
struct NostrBuildGIFResponse: Codable { | ||
let status: String | ||
let message: String | ||
let cursor: Int | ||
let count: Int | ||
let gifs: [NostrBuildGif] | ||
} | ||
|
||
struct NostrBuildGif: Codable, Identifiable { | ||
var id: String { bh } | ||
var url: String | ||
let bh: String | ||
} |
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,154 @@ | ||
// | ||
// NostrBuildGIFGrid.swift | ||
// damus | ||
// | ||
// Created by eric on 8/14/24. | ||
// | ||
|
||
import SwiftUI | ||
import Kingfisher | ||
|
||
|
||
struct NostrBuildGIFGrid: View { | ||
let damus_state: DamusState | ||
@State var results:[NostrBuildGif] = [] | ||
@State var cursor: Int = 0 | ||
@State var errorAlert: Bool = false | ||
@SceneStorage("NostrBuildGIFGrid.show_nsfw_alert") var show_nsfw_alert : Bool = true | ||
@SceneStorage("NostrBuildGIFGrid.persist_nsfw_alert") var persist_nsfw_alert : Bool = true | ||
@Environment(\.dismiss) var dismiss | ||
|
||
var onSelect:(String) -> () | ||
|
||
let columns = [ | ||
GridItem(.flexible()), | ||
GridItem(.flexible()), | ||
GridItem(.flexible()) | ||
] | ||
|
||
var TopBar: some View { | ||
VStack { | ||
HStack(spacing: 5.0) { | ||
|
||
Button(action: { | ||
Task { | ||
cursor -= 30 | ||
let response = try! await makeGIFRequest(cursor: cursor) | ||
self.results = response.gifs | ||
} | ||
}, label: { | ||
Text("Back", comment: "Button to go to previous page.") | ||
.padding(10) | ||
}) | ||
.buttonStyle(NeutralButtonStyle()) | ||
.opacity(cursor > 0 ? 1 : 0) | ||
.disabled(cursor == 0) | ||
|
||
Spacer() | ||
|
||
Image("nostrbuild") | ||
.resizable() | ||
.frame(width: 40, height: 40) | ||
|
||
Spacer() | ||
|
||
Button(NSLocalizedString("Next", comment: "Button to go to next page.")) { | ||
Task { | ||
cursor += 30 | ||
let response = try! await makeGIFRequest(cursor: cursor) | ||
self.results = response.gifs | ||
} | ||
} | ||
.bold() | ||
.buttonStyle(GradientButtonStyle(padding: 10)) | ||
} | ||
|
||
Divider() | ||
.foregroundColor(DamusColors.neutral3) | ||
.padding(.top, 5) | ||
} | ||
.frame(height: 30) | ||
.padding() | ||
.padding(.top, 15) | ||
} | ||
|
||
var body: some View { | ||
VStack { | ||
TopBar | ||
ScrollView { | ||
LazyVGrid(columns: columns, spacing: 5) { | ||
ForEach($results) { gifResult in | ||
VStack { | ||
if let url = URL(string: gifResult.url.wrappedValue) { | ||
ZStack { | ||
KFAnimatedImage(url) | ||
.cancelOnDisappear(true) | ||
.configure { view in | ||
view.framePreloadCount = 3 | ||
} | ||
.clipShape(RoundedRectangle(cornerRadius: 12.0)) | ||
.frame(width: 120, height: 120) | ||
.aspectRatio(contentMode: .fill) | ||
.onTapGesture { | ||
onSelect(url.absoluteString) | ||
dismiss() | ||
} | ||
if persist_nsfw_alert { | ||
Blur() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
Spacer() | ||
} | ||
} | ||
.padding() | ||
.alert("Error", isPresented: $errorAlert) { | ||
Button(NSLocalizedString("OK", comment: "Exit this view")) { | ||
dismiss() | ||
} | ||
} message: { | ||
Text("Failed to load GIFs") | ||
} | ||
.alert("NSFW", isPresented: $show_nsfw_alert) { | ||
Button(NSLocalizedString("Cancel", comment: "Exit this view")) { | ||
dismiss() | ||
} | ||
Button(NSLocalizedString("Proceed", comment: "Button to continue")) { | ||
show_nsfw_alert = false | ||
persist_nsfw_alert = false | ||
} | ||
} message: { | ||
Text("NSFW means \"Not Safe For Work\". The content in this view may be inappropriate to view in some situations and may contain explicit images.", comment: "Warning to the user that there may be content that is not safe for work.") | ||
} | ||
.onAppear { | ||
Task { | ||
await initial() | ||
} | ||
if persist_nsfw_alert { | ||
show_nsfw_alert = true | ||
} | ||
} | ||
} | ||
|
||
func initial() async { | ||
do { | ||
let response = try await makeGIFRequest(cursor: cursor) | ||
self.results = response.gifs | ||
} catch { | ||
print(error) | ||
errorAlert = true | ||
} | ||
|
||
} | ||
} | ||
|
||
struct NostrBuildGIFGrid_Previews: PreviewProvider { | ||
static var previews: some View { | ||
NostrBuildGIFGrid(damus_state: test_damus_state) { gifURL in | ||
print("GIF URL: \(gifURL)") | ||
} | ||
} | ||
} |
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