Skip to content

Commit

Permalink
spheron replaced with thirdweb
Browse files Browse the repository at this point in the history
  • Loading branch information
tempe-techie committed May 30, 2024
1 parent 70af524 commit ae321c0
Show file tree
Hide file tree
Showing 21 changed files with 715 additions and 470 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=
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,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
25 changes: 0 additions & 25 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 @@ -44,6 +44,7 @@
@processFileUrl="insertImage"
title="Upload image"
infoText="Upload an image."
storageType="imagekit"
:componentId="$.uid"
:maxFileSize="$config.fileUploadSizeLimit"
/>
Expand Down Expand Up @@ -384,6 +385,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
4 changes: 3 additions & 1 deletion components/chat/ChatPost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

<div class="card col-md-6">
<NuxtLink :to="'/nft/collection?id='+collection.address" class="text-decoration-none text-reset">
<img :src="collection?.image" class="card-img-top" />
<Image :url="collection?.image" :alt="collection?.name" cls="card-img-top" />

<div class="card-body bg-body rounded-bottom-3 border-end border-bottom border-start">
<h5 class="card-title text-break">{{ collection?.name }}</h5>
Expand Down Expand Up @@ -175,6 +175,7 @@ import sanitizeHtml from 'sanitize-html';
import { useEthers, shortenAddress } from 'vue-dapp';
import { useToast } from "vue-toastification/dist/index.mjs";
import { useUserStore } from '~/store/user';
import Image from "~/components/Image.vue";
import ProfileImage from "~/components/profile/ProfileImage.vue";
import IggyPostMint from "~/components/minted-posts/IggyPostMint.vue";
import MintedPostImage from '~/components/minted-posts/MintedPostImage.vue';
Expand All @@ -194,6 +195,7 @@ export default {
components: {
ChatQuote,
IggyPostMint,
Image,
MintedPostImage,
ProfileImage
},
Expand Down
7 changes: 4 additions & 3 deletions components/nft/collection/AddImageToCollectionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

<FileUploadInput
btnCls="btn btn-primary"
storageType="ipfs"
:maxFileSize="$config.fileUploadSizeLimit"
@processUploadedFileUrl="insertImageLink"
/>


<p class="mt-3">Or paste image link here:</p>
</div>
Expand All @@ -28,7 +28,7 @@
<input v-model="imageUrl" type="text" class="form-control" id="addImageToCollectionInput" />

<div v-if="imageUrl" class="mt-3">
<img :src="imageUrl" :key="imageUrl" class="img-thumbnail img-fluid" style="max-width: 100px;" />
<Image :url="imageUrl" alt="Image" 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>
</div>
Expand All @@ -51,13 +51,14 @@
import { ethers } from 'ethers';
import { useEthers } from 'vue-dapp';
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
8 changes: 5 additions & 3 deletions components/nft/collection/ChangeCollectionPreviewModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<FileUploadInput
btnCls="btn btn-primary"
:maxFileSize="$config.fileUploadSizeLimit"
storageType="ipfs"
@processUploadedFileUrl="insertImageLink"
/>

Expand All @@ -29,9 +30,9 @@
<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>
<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 @@ -52,14 +53,15 @@
import { ethers } from 'ethers';
import { useEthers } from 'vue-dapp';
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 Down
7 changes: 6 additions & 1 deletion components/nft/collection/RemoveImageFromCollectionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,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 class="btn btn-danger" @click="removeImage(index)" :disabled="waitingRemove || images.length == 1">
Expand All @@ -53,6 +53,7 @@
import { ethers } from 'ethers';
import { useEthers } from 'vue-dapp';
import { useToast } from "vue-toastification/dist/index.mjs";
import Image from "~/components/Image.vue";
import WaitingToast from "~/components/WaitingToast";
export default {
Expand All @@ -69,6 +70,10 @@ export default {
}
},
components: {
Image,
},
mounted() {
this.componentId = this.$.uid;
},
Expand Down
12 changes: 11 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,16 @@ 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 @@ -205,6 +205,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 ae321c0

Please sign in to comment.