Image sharing backed by ATProto
atproto images gleam

record/lexicon helper functions

Signed-off-by: Naomi Roberts <mia@naomieow.xyz>

lesbian.skin 47331808 28ecadad

verified
+104 -50
+14 -10
src/plonk.gleam
··· 249 249 html.main([attr.class("container")], [ 250 250 html.section([attr.class("content")], [ 251 251 header(option.is_some(model.handle)), 252 - case model.show_spinner { 253 - True -> loading_spinner() 254 - False -> element.none() 255 - }, 256 - // TODO: move to own page + login button in header 257 - case model.show_login { 258 - True -> login_container(model.login_form, model.login_busy) 259 - False -> element.none() 260 - }, 261 252 case model.route { 262 253 HomePage(home_model) -> 263 254 home.view(home_model) |> element.map(HomePageMsg) 264 255 ImageViewPage(image_view_model) -> 265 256 image_view.view(image_view_model) |> element.map(ImageViewPageMsg) 266 257 UploadPage(upload_model) -> 267 - upload.view(upload_model) |> element.map(UploadPageMsg) 258 + case model.show_spinner { 259 + True -> loading_spinner() 260 + False -> 261 + case model.agent { 262 + None -> html.text("Error: not logged in") 263 + Some(_) -> 264 + upload.view(upload_model) |> element.map(UploadPageMsg) 265 + } 266 + } 267 + }, 268 + // TODO: move to own page + login button in header 269 + case model.show_login { 270 + True -> login_container(model.login_form, model.login_busy) 271 + False -> element.none() 268 272 }, 269 273 ]), 270 274 ])
-29
src/plonk/atp.ffi.mjs
··· 125 125 /** 126 126 * 127 127 * @param {Agent} agent 128 - * @param {BlobRef} blobRef 129 - * @param {String} title 130 - * @returns 131 - */ 132 - export async function createImageRecord(agent, blobRef, title) { 133 - let res; 134 - try { 135 - res = await agent.com.atproto.repo.createRecord({ 136 - repo: agent.did, 137 - collection: "top.plonk.image", 138 - record: { 139 - $type: "top.plonk.image", 140 - title: title, 141 - content: blobRef, 142 - createdAt: new Date().toISOString(), 143 - }, 144 - }); 145 - if (!res.success) { 146 - return Result$Error(JSON.stringify(res)); 147 - } 148 - return Result$Ok(res.data); 149 - } catch (err) { 150 - return Result$Error(`${err}`); 151 - } 152 - } 153 - 154 - /** 155 - * 156 - * @param {Agent} agent 157 128 * @param {ComAtprotoRepoUploadBlob.InputSchema} blob 158 129 * @param {ComAtprotoRepoUploadBlob.CallOptions?} options 159 130 * @returns {Promise<Result<ComAtprotoRepoUploadBlob.OutputSchema, null>>}
-9
src/plonk/atp.gleam
··· 73 73 74 74 @external(javascript, "./atp.ffi.mjs", "blobRef") 75 75 pub fn get_blob_ref(output_schema _: BlobOutputSchema) -> BlobRef 76 - 77 - pub type CreateRecordOutputSchema 78 - 79 - @external(javascript, "./atp.ffi.mjs", "createImageRecord") 80 - pub fn create_image_record( 81 - agent _: Agent, 82 - blob_ref _: BlobRef, 83 - title _: String, 84 - ) -> promise.Promise(Result(CreateRecordOutputSchema, String))
+3 -2
src/plonk/pages/upload.gleam
··· 8 8 import plonk/atp 9 9 import plonk/file 10 10 import plonk/forms 11 + import plonk/record/image 11 12 12 13 pub type Model { 13 14 Model(upload_is_busy: Bool, files: List(file.File)) ··· 16 17 pub type Msg { 17 18 UserSubmittedUploadForm(formdata: List(#(String, forms.FormDataType))) 18 19 ClientUploadedBlob(result: Result(atp.BlobOutputSchema, Nil)) 19 - ClientCreatedRecord(result: Result(atp.CreateRecordOutputSchema, String)) 20 + ClientCreatedRecord(result: Result(image.OutputSchema, String)) 20 21 } 21 22 22 23 pub fn init(_flags: Nil) -> #(Model, effect.Effect(Msg)) { ··· 64 65 ClientUploadedBlob(result: Ok(output_schema)) -> #( 65 66 model, 66 67 effect.from(fn(dispatch) { 67 - atp.create_image_record(agent, atp.get_blob_ref(output_schema:), "") 68 + image.create_record(agent, "", "", atp.get_blob_ref(output_schema:)) 68 69 |> promise.map(ClientCreatedRecord) 69 70 |> promise.tap(dispatch) 70 71 Nil
+48
src/plonk/record/image.ffi.mjs
··· 1 + import { ComAtprotoRepoCreateRecord } from "@atproto/api"; 2 + 3 + /** 4 + * 5 + * @param {Agent} agent 6 + * @param {String} title 7 + * @param {String} description 8 + * @param {BlobRef} blobRef 9 + * @returns {Promise<Result<ComAtprotoRepoCreateRecord.OutputSchema, String>>} 10 + */ 11 + export async function createRecord(agent, title, description, blobRef) { 12 + let res; 13 + try { 14 + res = await agent.com.atproto.repo.createRecord({ 15 + repo: agent.did, 16 + collection: "top.plonk.image", 17 + record: { 18 + $type: "top.plonk.image", 19 + title: title, 20 + description: description, 21 + content: blobRef, 22 + createdAt: new Date().toISOString(), 23 + }, 24 + }); 25 + if (!res.success) { 26 + return Result$Error(JSON.stringify(res)); 27 + } 28 + return Result$Ok(res.data); 29 + } catch (err) { 30 + return Result$Error(`${err}`); 31 + } 32 + } 33 + 34 + /** 35 + * @param {ComAtprotoRepoCreateRecord.OutputSchema} output 36 + * @returns {String} uri 37 + */ 38 + export function getUri(output) { 39 + return output.uri; 40 + } 41 + 42 + /** 43 + * @param {ComAtprotoRepoCreateRecord.OutputSchema} output 44 + * @returns {String} cid 45 + */ 46 + export function getCid(output) { 47 + return output.cid; 48 + }
+39
src/plonk/record/image.gleam
··· 1 + import gleam/javascript/promise 2 + import gleam/result 3 + import plonk/atp 4 + 5 + pub type OutputSchema { 6 + OutputSchema(uri: String, cid: String) 7 + } 8 + 9 + type CreateRecordOutputSchema 10 + 11 + pub fn create_record( 12 + agent: atp.Agent, 13 + title: String, 14 + description: String, 15 + content: atp.BlobRef, 16 + ) -> promise.Promise(Result(OutputSchema, String)) { 17 + do_create_record(agent, title, description, content) 18 + |> promise.map(fn(r) { 19 + result.map(r, fn(output_schema) { 20 + let uri = get_uri(output_schema) 21 + let cid = get_cid(output_schema) 22 + OutputSchema(uri:, cid:) 23 + }) 24 + }) 25 + } 26 + 27 + @external(javascript, "./image.ffi.mjs", "createRecord") 28 + fn do_create_record( 29 + agent _: atp.Agent, 30 + title _: String, 31 + description _: String, 32 + content _: atp.BlobRef, 33 + ) -> promise.Promise(Result(CreateRecordOutputSchema, String)) 34 + 35 + @external(javascript, "./image.ffi.mjs", "getUri") 36 + fn get_uri(output: CreateRecordOutputSchema) -> String 37 + 38 + @external(javascript, "./image.ffi.mjs", "getCid") 39 + fn get_cid(output: CreateRecordOutputSchema) -> String