How to add inline content in an authenticated Solid App?

I’m quite new to front-end development, so bare with me. Using the solid-client-authn-browser I know how to create an Javascript app to retrieve private content from a Solid Pod.

E.g. a folder demo on my Pod is protected with ACL-s. After authentication I get a special fetch object with contains all the tools to retrieve private data from my demo folder. So far so good.

Now I am trying to generate HTML based on the data I find in the demo folder, e.g. a list of images. These images I would like to display inline using generated HTML:

<ul>
 <li><img src="{url-to-private-image}"> {name of image}</li>
 ...
</ul>

I can access the image data in JavaScript. I can access any private data about this image in JavaScript. But my browser doesn’t know what to do with inline HTML content. It tries to fetch these resources using an unauthenticated fetch.

Any hints how other implementors tackled this issue?

Essentially you do have to set the data programmatically because the only way to access the private data is via JS.

Here’s what I ended up doing in my app using svelte based on your repo on github (thanks!)
(Apologies for the formatting)

<script>
let fetch
// When we are logged in we get a fresh session object
    session.subscribe( s => {
        if (s) {
          fetch = s.fetch 

fetch(imgurl).then(x=>x.blob()).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  imgdata = objectURL;
});
        }
    });
</script>

{#await imgdata}
Loading...
{:then}
          <img src={imgdata} >
{:catch error}
        <p style="color: red">{error.message}</p>
{/await}
1 Like

Super that worked like a charm!

1 Like

Great!
I should add that I’m still getting my head around using fetch with svelte’s #await

Even though it works, I think this code might actually be wrong in that loading is never shown because imgdata is not a promise.
So there’s two further variants:

  1. assign the output of the fetch sequence directly to imgdata, so that it is a promise and #await works correctly
  2. remove the code for #await and add manual loading and error reactive variables with #if statements to have the desired effect

I started with Svelte a week ago, so I’m not going to attempt to show the right solution :slight_smile:

I ended up transforming it into a Promise like:

<script>
    // SolidImage.svelte
    // Use as:
    // <SolidImage src="URL" alt="Alt message"/>
    //

    import { onMount } from "svelte";

    export let src;
    export let alt;

    let imageData;

    onMount( async() => {
        const response = await fetch(src);
        const blob = await response.blob();
        imageData = URL.createObjectURL(blob);
    });
</script>

{#if imageData}
    {#await imageData}
        Loading...
    {:then}
        <img src={imageData} alt={alt}/>
    {:catch error}
        <p class="error">{error.message}</p>
    {/await}
{/if}

<style>
    img {
        width: 100%;
        height: auto;
    }
</style>

But I’m thinking that maybe at some point I will need something as Svelte Query to add more intelligence in caching, updates of fetches. But I’ll stick now to easy examples for demonstration purposes.

1 Like