Skip to content

Commit

Permalink
🛼🎨 ↝ New screenshot feature for the Planet Editor
Browse files Browse the repository at this point in the history
Changelog:
Moved the gallery components into the offchain account section.
Added new feature where users can take a screenshot of the planet they've created

Currently, the screenshot is saved as an image URI string (see bottom of commit for e.g.), which is a problem as it is then uploaded to Supabase as a URI. What we need to do is convert the URI to an image inside the app (without saving it as a file on the app (as in a png file being saved next to the jsx file). This could be done before it's uploaded to Supabase, or when it's retrieved...

Signal-K/sytizen#18
Signal-K/sytizen#16
  • Loading branch information
Gizmotronn committed Jan 25, 2023
1 parent 75ed71b commit 8c2eb2e
Show file tree
Hide file tree
Showing 8 changed files with 780 additions and 119 deletions.
148 changes: 147 additions & 1 deletion components/Data/OffchainAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { useState, useEffect } from "react";
import React, { useState, createRef, useEffect } from "react";
import { useUser, useSupabaseClient, Session } from "@supabase/auth-helpers-react";
import { Database } from '../../utils/database.types';
import AccountAvatar from "./AccountAvatar";
import { imagesCdnAddress } from "../../constants/cdn";
import { v4 as uuidv4 } from 'uuid';
import Link from "next/link";
import { Container, Form, Button, Row, Col, Card } from "react-bootstrap";
import PlanetEditor from "../../pages/generator/planet-editor";
import { useScreenshot } from "use-react-screenshot";

type Profiles = Database['public']['Tables']['profiles']['Row'];

Expand All @@ -13,6 +19,13 @@ export default function OffchainAccount({ session }: { session: Session}) {
const [website, setWebsite] = useState<Profiles['website']>(null); // I believe this is the email field
const [avatar_url, setAvatarUrl] = useState<Profiles['avatar_url']>(null);
const [address, setAddress] = useState<Profiles['address']>(null); // This should be set by the handler eventually (connected address).
const [images, setImages] = useState([]);

const ref = createRef();
let width = '1080'
const [image, takeScreenShot] = useScreenshot();

const getImage = () => takeScreenShot(ref.current);

useEffect(() => {
getProfile();
Expand Down Expand Up @@ -79,6 +92,92 @@ export default function OffchainAccount({ session }: { session: Session}) {
}
}

// Gallery components
// Retrieving gallery data for user
async function getImages() {
const { data, error } = await supabase
.storage
.from('images')
.list(user?.id + '/', {
limit: 100, // Get 100 images from this dir
offset: 0,
sortBy: {
column: 'name',
order: 'asc'
}
});

if ( data !== null ) {
setImages(data);
} else {
alert('Error loading images');
console.log(error);
}
}

async function uploadImage(e) {
let file = e.target.files[0];
const { data, error } = await supabase
.storage
.from('images')
.upload(user.id + '/' + uuidv4(), file);

if (data) {
getImages();
} else {
console.log(error);
}
}

async function uploadScreenshot(e) {
let file = image + '.png';
const { data, error } = await supabase
.storage
.from('images')
.upload(user.id + '/' + uuidv4(), file);

if (data) {
getImages();
} else {
console.log(error);
}
}

async function deleteImage (imageName) {
const { error } = await supabase
.storage
.from('images')
.remove([ user.id + '/' + imageName ])

if (error) {
alert (error);
} else {
getImages();
}
}

useEffect(() => {
if (user) { // Only get images IF the user exists and is logged in
getImages(); // Add a getPosts function to get a user's profile posts
}
}, [user]);

function convertURIToImageData(URI) {
return new Promise(function(resolve, reject) {
if (URI == null) return reject();
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
image = new Image();
image.addEventListener('load', function() {
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0, canvas.width, canvas.height);
resolve(context.getImageData(0, 0, canvas.width, canvas.height));
}, false);
image.src = URI;
});
}

return (
<div className="form-widget">
<AccountAvatar
Expand Down Expand Up @@ -130,6 +229,53 @@ export default function OffchainAccount({ session }: { session: Session}) {
{loading ? 'Loading ...' : 'Update'}
</button>
</div>
<br />
<div>
<button style={{ marginBottom: "10px" }} onClick={getImage}>
Take screenshot
</button>
</div>
<img width={width} src={image} alt={"ScreenShot"} />
<div
ref={ref as React.RefObject<HTMLDivElement>}
style={{
border: "1px solid #ccc",
padding: "10px",
marginTop: "20px"
}}
>
<PlanetEditor />
</div>
<br />
<Container className='container-sm mt-4'>
<>
<h1>Your photos</h1>
<br />
<p>Upload image of your model for analysis</p>
<Form.Group className="mb-3" style={{maxWidth: '500px'}}>
<Form.Control type='file' accept='image/png, image/jpeg' onChange={(e) => uploadImage(e)} />
</Form.Group>
<Button variant='outline-info' onClick={() => uploadScreenshot(image)} />
<br />
<hr />
<br />
<h3>Your images</h3>
<Row className='g-4'>
{images.map((image) => {
return (
<Col key={imagesCdnAddress + user.id + '/' + image.name}>
<Card>
<Card.Img variant='top' src={imagesCdnAddress + user.id + '/' + image.name} />
<Card.Body>
<Button variant='danger' onClick={() => deleteImage(image.name)}>Delete image</Button>
</Card.Body>
</Card>
</Col>
)
})}
</Row>
</>
</Container>
<div>
<button className="button block" onClick={() => supabase.auth.signOut()}>
Sign Out
Expand Down
1 change: 1 addition & 0 deletions generator/services/planet-editor-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class PlanetEditorSceneManager implements SceneManager {
canvas.width = canvas.height;// * (16 / 9);

this._renderer = new THREE.WebGLRenderer({
preserveDrawingBuffer: true,
canvas,
antialias: true
});
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"ethers": "^5.7.2",
"framer-motion": "^6",
"graphql": "^16.6.0",
"html2canvas": "^1.4.1",
"image-data-uri": "^2.0.1",
"moralis": "^2.10.3",
"moralis-v1": "^1.12.0",
"next": "^13.1.4",
Expand All @@ -63,6 +65,7 @@
"supabase": "^1.34.5",
"swr": "^2.0.0",
"three": "0.108.0",
"use-react-screenshot": "^3.0.0",
"uuid": "^9.0.0",
"uuidv4": "^6.2.13",
"web3uikit": "^1.0.4"
Expand Down
111 changes: 0 additions & 111 deletions pages/gallery/index.jsx

This file was deleted.

Loading

1 comment on commit 8c2eb2e

@Gizmotronn
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.