Skip to content

Commit

Permalink
uploading images to ThirdWeb instead of Spheron
Browse files Browse the repository at this point in the history
  • Loading branch information
tempe-techie committed May 30, 2024
1 parent 3e35116 commit 5b3beb1
Show file tree
Hide file tree
Showing 21 changed files with 631 additions and 361 deletions.
5 changes: 2 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ IMAGEKIT_PUBLIC_KEY=
IMAGEKIT_PRIVATE_KEY=
LINK_PREVIEW_SERVICE=
RPC_CUSTOM=
SPHERON_BUCKET_NAME=
SPHERON_STORAGE_TOKEN=
TENOR_KEY=
TENOR_KEY=
THIRDWEB_CLIENT_ID=
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ jobs:
timeout-minutes: 20
env: # Environment variables from either organization or repository settings page (for GitHub Actions).
TENOR_KEY: ${{ secrets.TENOR_KEY }}
SPHERON_BUCKET_NAME: ${{ secrets.SPHERON_BUCKET_NAME }}
SPHERON_STORAGE_TOKEN: ${{ secrets.SPHERON_STORAGE_TOKEN }}
THIRDWEB_CLIENT_ID: ${{ secrets.THIRDWEB_CLIENT_ID }}
IMAGEKIT_ENDPOINT: ${{ secrets.IMAGEKIT_ENDPOINT }}
IMAGEKIT_PUBLIC_KEY: ${{ secrets.IMAGEKIT_PUBLIC_KEY }}
IMAGEKIT_PRIVATE_KEY: ${{ secrets.IMAGEKIT_PRIVATE_KEY }}
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,21 @@ If you want to have GIF search implemented, create your own Tenor API Key on Goo

Then enter the key in environment variables (`TENOR_KEY`).

## Image upload (Spheron/IPFS)
## Image upload (ThirdWeb/IPFS)

To support image uploads on IPFS please create a key/token on Spheron Storage: https://app.spheron.network/#/storage
To support image uploads on IPFS please create an API key on ThirdWeb: https://thirdweb.com/dashboard/settings/api-keys

Then add this key (and your bucket ID/name) to your environment variables:
Make sure to whitelist only your website domain/URL. And also restrict (toggle off) the API key usage for other services apart from Storage Upload service (even Storage Download is not needed).

Then add the Client ID of your API key to your environment variables:

```bash
SPHERON_BUCKET_NAME=
SPHERON_STORAGE_TOKEN=
THIRDWEB_CLIENT_ID=
```

Image uploads via Spheron work only if you have Netlify/Vercel background functions enabled (see `netlify/functions/imageUploader.js`).

## Image upload fallback

It is recommended to use ImageKit as the fallback option, in case Spheron has technical issues.
It is recommended to use ImageKit as the fallback option, in case ThirdWeb has technical issues.

For this to work, create an account at [ImageKit.io](https://imagekit.io/) and add these environment variables to your project:

Expand Down
24 changes: 0 additions & 24 deletions api/imageUploader.js

This file was deleted.

81 changes: 81 additions & 0 deletions components/Image.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<div>
<img @load="loading=false" :src="parseImageLink" @error="handleLoadError" :alt="alt" :class="cls" />
<div class="d-flex justify-content-center">
<span v-if="loading" class="spinner-grow spinner-grow-lg" role="status" aria-hidden="true"></span>
</div>

</div>
</template>

<script>
export default {
name: "Image",
props: ["alt", "cls", "url"],
data() {
return {
cid: null,
imageUrl: null,
loading: true,
};
},
mounted() {
this.fetchImageData();
},
computed: {
parseImageLink() {
let parsedImage = this.imageUrl;
if (parsedImage && parsedImage.includes("ipfs://")) {
parsedImage = parsedImage.replace("ipfs://", this.$config.ipfsGateway);
}
return parsedImage;
},
},
methods: {
fetchImageData() {
this.imageUrl = this.url;
if (this.url) {
if (this.url.startsWith(this.$config.ipfsGateway)) {
this.cid = this.url.replace(this.$config.ipfsGateway, "");
} else if (this.url.startsWith(this.$config.ipfsGateway2)) {
this.cid = this.url.replace(this.$config.ipfsGateway2, "");
} else if (this.url.startsWith(this.$config.ipfsGateway3)) {
this.cid = this.url.replace(this.$config.ipfsGateway3, "");
} else if (this.url.startsWith("https://cloudflare-ipfs.com/ipfs/")) {
this.cid = this.url.replace("https://cloudflare-ipfs.com/ipfs/", "");
} else if (this.url.startsWith("https://ipfs.io/ipfs/")) {
this.cid = this.url.replace("https://ipfs.io/ipfs/", "");
} else if (this.url.startsWith("ipfs://")) {
this.cid = this.url.replace("ipfs://", "");
} else if (this.url.startsWith("https://ipfs.itslit.org/ipfs/")) {
this.cid = this.url.replace("https://ipfs.itslit.org/ipfs/", "");
} else if (this.url.startsWith("https://ipfs.dylmusic.com/ipfs/")) {
this.cid = this.url.replace("https://ipfs.dylmusic.com/ipfs/", "");
}
}
},
handleLoadError() {
if (this.cid) {
if (this.imageUrl.startsWith(this.$config.ipfsGateway)) {
return this.imageUrl = this.$config.ipfsGateway3 + this.cid;
} else if (this.imageUrl.startsWith(this.$config.ipfsGateway3)) {
return this.imageUrl = this.$config.ipfsGateway2 + this.cid;
}
}
this.imageUrl = "https://placeholder.pics/svg/300/8e85e6/ffffff/loading%20error";
this.loading = false;
return;
},
},
}
</script>
9 changes: 9 additions & 0 deletions components/chat/ChatFeed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
@processFileUrl="insertImage"
title="Upload image"
infoText="Upload an image."
storageType="ipfs"
:componentId="$.uid"
:maxFileSize="$config.fileUploadSizeLimit"
/>
Expand Down Expand Up @@ -420,6 +421,14 @@ export default {
},
async insertImage(imageUrl) {
if (imageUrl.startsWith("ipfs://")) {
imageUrl = imageUrl.replace("ipfs://", this.$config.ipfsGateway);
}
if (imageUrl.endsWith(".JPG") || imageUrl.endsWith(".PNG") || imageUrl.endsWith(".JPEG") || imageUrl.endsWith(".GIF")) {
imageUrl = imageUrl.replace(".JPG", ".jpg").replace(".PNG", ".png").replace(".JPEG", ".jpeg").replace(".GIF", ".gif");
}
// add image url to postText
if (!this.postText) {
this.postText = imageUrl + ' '
Expand Down
12 changes: 7 additions & 5 deletions components/nft/collection/AddImageToCollectionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

<FileUploadInput
btnCls="btn btn-primary"
storageType="ipfs"
:maxFileSize="$config.fileUploadSizeLimit"
@processUploadedFileUrl="insertImageLink"
/>
Expand All @@ -38,15 +39,15 @@
<input v-model="imageUrl" type="text" class="form-control" id="addImageToCollectionInput" />

<div v-if="imageUrl" class="mt-3">
<img
:src="imageUrl"
<Image
:url="imageUrl"
:key="imageUrl"
class="img-thumbnail img-fluid"
cls="img-thumbnail img-fluid"
style="max-width: 100px"
/>
<br />
<small
>If image didn't appear above, then something is wrong with the link you added.</small
>If image didn't appear above, then something is wrong with the link you added (wait until the loading indicator completes).</small
>
</div>
</div>
Expand All @@ -72,13 +73,14 @@
import { ethers } from 'ethers'
import { useEthers } from '~/store/ethers'
import { useToast } from 'vue-toastification/dist/index.mjs'
import Image from '~/components/Image.vue'
import WaitingToast from '~/components/WaitingToast'
import FileUploadInput from '~/components/storage/FileUploadInput.vue'
export default {
name: 'AddImageToCollectionModal',
props: ['cAddress', 'mdAddress'],
components: { FileUploadInput },
components: { FileUploadInput, Image },
data() {
return {
Expand Down
20 changes: 17 additions & 3 deletions components/nft/collection/ChangeCollectionPreviewModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<FileUploadInput
btnCls="btn btn-primary"
storageType="ipfs"
:maxFileSize="$config.fileUploadSizeLimit"
@processUploadedFileUrl="insertImageLink"
/>
Expand All @@ -40,10 +41,10 @@
<input v-model="imageUrl" type="text" class="form-control" />

<div v-if="imageUrl" class="mt-3">
<img :src="imageUrl" class="img-thumbnail img-fluid" style="max-width: 100px" />
<Image :url="imageUrl" cls="img-thumbnail img-fluid" style="max-width: 100px" />
<br />
<small
>If image didn't appear above, then something is wrong with the link you added.</small
>If image didn't appear above, then something is wrong with the link you added (wait until the loading indicator completes).</small
>
</div>
</div>
Expand All @@ -69,14 +70,15 @@
import { ethers } from 'ethers'
import { useEthers } from '~/store/ethers'
import { useToast } from 'vue-toastification/dist/index.mjs'
import Image from '~/components/Image.vue'
import WaitingToast from '~/components/WaitingToast'
import FileUploadInput from '~/components/storage/FileUploadInput.vue'
export default {
name: 'ChangeCollectionPreviewModal',
props: ['cAddress', 'mdAddress'],
emits: ['saveCollection'],
components: { FileUploadInput },
components: { FileUploadInput, Image },
data() {
return {
Expand All @@ -90,6 +92,18 @@ export default {
this.componentId = this.$.uid
},
computed: {
parseImageLink() {
let parsedImage = this.imageUrl;
if (parsedImage && parsedImage.includes("ipfs://")) {
parsedImage = parsedImage.replace("ipfs://", this.$config.ipfsGateway);
}
return parsedImage;
}
},
methods: {
async updateImage() {
this.waiting = true
Expand Down
7 changes: 6 additions & 1 deletion components/nft/collection/RemoveImageFromCollectionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<div class="row mt-3" v-if="images">
<div v-for="(image, index) in images" :key="image" class="col-md-4 mb-3">
<div class="card">
<img :src="image" class="card-img-top" />
<Image :url="image" alt="Image" cls="card-img-top" />
<div class="card-body">
<div class="row">
<button
Expand Down Expand Up @@ -70,6 +70,7 @@
import { ethers } from 'ethers'
import { useEthers } from '~/store/ethers'
import { useToast } from 'vue-toastification/dist/index.mjs'
import Image from '~/components/Image.vue'
import WaitingToast from '~/components/WaitingToast'
export default {
Expand All @@ -86,6 +87,10 @@ export default {
}
},
components: {
Image,
},
mounted() {
this.componentId = this.$.uid
},
Expand Down
14 changes: 13 additions & 1 deletion components/profile/ProfileImage.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<img :src="imgPath" />
<img :src="parseImageLink" />
</template>

<script>
Expand Down Expand Up @@ -29,6 +29,18 @@ export default {
}
},
computed: {
parseImageLink() {
let parsedImage = this.imgPath;
if (parsedImage && parsedImage.includes("ipfs://")) {
parsedImage = parsedImage.replace("ipfs://", this.$config.ipfsGateway);
}
return parsedImage;
}
},
watch: {
image(oldValue, newValue) {
if (newValue) {
Expand Down
1 change: 1 addition & 0 deletions components/profile/PunkProfile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
@processFileUrl="insertImage"
title="Change profile image"
infoText="Upload a new profile picture."
storageType="ipfs"
:componentId="$.uid"
:maxFileSize="$config.fileUploadSizeLimit"
/>
Expand Down
Loading

0 comments on commit 5b3beb1

Please sign in to comment.