diff --git a/src/components/Assets.jsx b/src/components/Assets.jsx
index a78231a..7ebc433 100644
--- a/src/components/Assets.jsx
+++ b/src/components/Assets.jsx
@@ -1,37 +1,64 @@
import React, { useState, useEffect } from 'react';
import firebase from 'firebase/app';
import 'firebase/storage';
+import { Stack } from './Stack';
const Assets = () => {
const [files, setFiles] = useState([]);
+ const [isFetchingFiles, setIsFetchingFiles] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [filteredFiles, setFilteredFiles] = useState([]);
+ const [isUploading, setIsUploading] = useState(false);
+ const [uploadProgress, setUploadProgress] = useState();
+ const [listType, setListType] = useState('grid');
+
const storageRef = firebase.storage().ref(`assets/${window.user.uid}`);
- // Function to handle file upload
- const handleFileUpload = e => {
- const file = e.target.files[0];
-
+ const uploadFile = file => {
if (file.size > 5 * 1024 * 1024) {
// 5MB limit
alert('File size must be less than 5MB');
return;
}
+ setIsUploading(true);
const fileRef = storageRef.child(file.name);
- fileRef
- .put(file)
- .then(() => {
- alert('File uploaded successfully');
- fetchFiles();
- })
- .catch(error => {
+ const task = fileRef.put(file);
+
+ task.on(
+ 'state_changed',
+ snapshot => {
+ // Observe state change events such as progress, pause, and resume
+ // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
+ var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
+ console.log('Upload is ' + progress + '% done');
+ },
+ error => {
+ // Handle unsuccessful uploads
+ setIsUploading(false);
console.error('File upload error:', error);
- });
+ },
+ () => {
+ // uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
+ // console.log('File available at', downloadURL);
+ // });
+
+ alertsService.add('File uploaded successfully');
+
+ fetchFiles();
+ setIsUploading(false);
+ }
+ );
+ };
+ // Function to handle file upload
+ const handleFileUpload = e => {
+ const file = e.target.files[0];
+ uploadFile(file);
};
// Function to fetch existing files
const fetchFiles = () => {
+ setIsFetchingFiles(true);
storageRef
.listAll()
.then(result => {
@@ -42,9 +69,11 @@ const Assets = () => {
});
Promise.all(filePromises).then(setFiles);
+ setIsFetchingFiles(false);
})
.catch(error => {
console.error('File fetch error:', error);
+ setIsFetchingFiles(false);
});
};
@@ -73,56 +102,99 @@ const Assets = () => {
const [isDropTarget, setIsDropTarget] = useState(false);
const handleDragDropEvent = e => {
console.log('drag event, ', e.type);
- if (e.type === 'dragleave' || e.type === 'drop') {
+ if (e.type === 'dragover') {
+ // required for drop to work
+ e.preventDefault();
+ } else if (e.type === 'dragleave') {
+ e.preventDefault();
setIsDropTarget(false);
- }
- if (e.type === 'dragenter') {
+ } else if (e.type === 'dragenter') {
setIsDropTarget(true);
- ode;
- console.log(999, e.type);
}
};
+ const handleDrop = e => {
+ e.preventDefault();
+ console.log('drop');
+ setIsDropTarget(false);
+
+ if (e.dataTransfer.items) {
+ const file = e.dataTransfer.items[0].getAsFile();
+ uploadFile(file);
+ }
+ };
+
+ const copyFileUrl = url => {
+ const input = document.createElement('input');
+ input.value = url;
+ input.style.opacity = 0;
+ document.body.appendChild(input);
+ input.select();
+ document.execCommand('copy');
+ document.body.removeChild(input);
+ alertsService.add('File URL copied!');
+ };
+
return (
-
+
{
- handleDragDropEvent(e);
- // setFiles(e, 'a');
- }}
>
-
Drop file here to upload
-
+ {isUploading ?
: null}
+
+
+
Drop file here to upload
+
+
+ {isFetchingFiles &&
Fetching your files...
}
{files.length ? (
-
+
+
+
+
+
) : null}
-
);
};
diff --git a/src/components/app.jsx b/src/components/app.jsx
index 80bc72d..c77d598 100644
--- a/src/components/app.jsx
+++ b/src/components/app.jsx
@@ -100,6 +100,7 @@ export default class App extends Component {
constructor() {
super();
this.AUTO_SAVE_INTERVAL = 15000; // 15 seconds
+ const savedUser = window.localStorage.getItem('user');
this.modalDefaultStates = {
isModalOpen: false,
isAddLibraryModalOpen: false,
@@ -125,7 +126,8 @@ export default class App extends Component {
title: '',
externalLibs: { js: '', css: '' }
},
- catalogs: {}
+ catalogs: {},
+ user: savedUser
};
this.defaultSettings = {
preserveLastCode: true,
@@ -158,6 +160,10 @@ export default class App extends Component {
};
this.prefs = {};
+ if (savedUser) {
+ window.user = savedUser;
+ }
+
firebase.auth().onAuthStateChanged(user => {
this.setState({ isLoginModalOpen: false });
if (user) {
@@ -165,6 +171,7 @@ export default class App extends Component {
alertsService.add('You are now logged in!');
this.setState({ user });
window.user = user;
+ window.localStorage.setItem('user', user);
if (!window.localStorage[LocalStorageKeys.ASKED_TO_IMPORT_CREATIONS]) {
this.fetchItems(false, true).then(items => {
if (!items.length) {
diff --git a/src/style.css b/src/style.css
index cf78ee7..743f5de 100644
--- a/src/style.css
+++ b/src/style.css
@@ -85,6 +85,7 @@ p {
button {
font-family: inherit;
font-size: 100%;
+ cursor: pointer;
}
.hide {
@@ -571,7 +572,9 @@ body:not(.light-version).overlay-visible .main-container {
overflow: hidden;
position: relative;
background: var(--color-bg);
- transition: height 0.3s ease, width 0.3s ease;
+ transition:
+ height 0.3s ease,
+ width 0.3s ease;
will-change: height;
}
@@ -2002,13 +2005,103 @@ while the theme CSS file is loading */
justify-content: center;
}
-.asset_manager__upload-box {
+.asset-manager__upload-box {
padding: 1rem 2rem;
border: 3px dashed rgb(255 255 255 / 10%);
border-radius: 1rem;
text-align: center;
margin-bottom: 1rem;
transition: 0.3s ease;
+ position: relative;
+}
+
+@keyframes move {
+ 0% {
+ background-position: 0 0;
+ }
+ 100% {
+ background-position: 50px 50px;
+ }
+}
+
+.asset-manager__progress-bar {
+ position: absolute;
+ inset: 1rem;
+ /* height: 2rem; */
+ background-image: linear-gradient(
+ -45deg,
+ rgba(255, 255, 255, 0.2) 25%,
+ transparent 25%,
+ transparent 50%,
+ rgba(255, 255, 255, 0.2) 50%,
+ rgba(255, 255, 255, 0.2) 75%,
+ transparent 75%,
+ transparent
+ );
+ z-index: 1;
+ background-size: 50px 50px;
+ animation: move 2s linear infinite;
+ border-top-right-radius: 8px;
+ border-bottom-right-radius: 8px;
+ border-top-left-radius: 20px;
+ border-bottom-left-radius: 20px;
+ overflow: hidden;
+}
+.asset-manager__file {
+ /* list-style: none; */
+ /* padding: 0; */
+ /* margin: 0; */
+ display: flex;
+ background: rgb(255 255 255 / 4%);
+ gap: 0.5rem;
+ padding: 0.2rem;
+ border-radius: 0.4rem;
+ color: inherit;
+ border: 0;
+ transition: 0.3s ease;
+ /* align-items: center; */
+}
+.asset-manager__file:hover {
+ background: rgb(255 255 255 / 7%);
+}
+.asset-manager__file--grid {
+ display: flex;
+ flex-direction: column;
+ /* align-items: flex-start; */
+}
+.asset-manager__file-container {
+ padding: 0;
+ gap: 0.3rem;
+}
+.asset-manager__file-container--grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
+}
+
+.asset-manager__file {
+ display: flex;
+ gap: 0.5rem;
+}
+.asset-manager__file-name {
+ max-width: 100%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.asset-manager__file img {
+ height: 1.5rem;
+ aspect-ratio: 1;
+ /* border-radius: 0.5rem; */
+ object-fit: cover;
+}
+.asset-manager__file--grid img {
+ height: 80px;
+}
+.stack {
+ display: flex;
+}
+.stack > * {
+ margin: 0;
}
@media screen and (max-width: 600px) {