move to react

This commit is contained in:
matan
2024-01-05 13:24:35 +02:00
parent 18bb5ce874
commit 7eab1c2763
18 changed files with 31104 additions and 349 deletions
+1
View File
@@ -0,0 +1 @@
**/node_modules/*
+56 -19
View File
@@ -6,34 +6,71 @@ import requests
from zipfile import ZipFile
import requests
WEB_DIRECTORY = 'javascript'
NODE_CLASS_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS = {}
def transform_css_to_js(css_content):
js_content = """
var docStyle = document.createElement('style');
docStyle.innerHTML = `""" + css_content.replace('`', r'\`').replace('\\', r'\\') + """
`;
document.head.appendChild(docStyle);
"""
return js_content
def transform_files_in_folder(folder_path):
for filename in os.listdir(folder_path):
if filename.endswith(".css"):
css_file_path = os.path.join(folder_path, filename)
js_file_path = os.path.join(folder_path, filename[:-4] + ".css.js")
with open(css_file_path, 'r') as css_file:
css_content = css_file.read()
js_content = transform_css_to_js(css_content)
with open(js_file_path, 'w') as js_file:
js_file.write(js_content)
github_repo_url = "https://github.com/OpenArt-AI/ComfyUI-Assistant"
zip_url = f"{github_repo_url}/archive/main.zip"
script_directory = os.path.dirname(os.path.realpath(__file__))
javascript_folder = os.path.join(script_directory, "javascript")
temp_zip_path = os.path.join(script_directory, "main.zip")
temp_extracted_folder = os.path.join(script_directory, "temp_extracted")
# Download the ZIP file
response = requests.get(zip_url)
if response.status_code == 200:
with open(temp_zip_path, "wb") as temp_zip_file:
temp_zip_file.write(response.content)
if os.getenv("COMFY_ASSISTANT_ENV") == "DEV":
print("Skipping auto-upgrade")
else:
# Download the ZIP file
response = requests.get(zip_url)
if response.status_code == 200:
with open(temp_zip_path, "wb") as temp_zip_file:
temp_zip_file.write(response.content)
# Extract the contents of the ZIP file to a temporary folder
with ZipFile(temp_zip_path, 'r') as zip_ref:
zip_ref.extractall(temp_extracted_folder)
# Extract the contents of the ZIP file to a temporary folder
with ZipFile(temp_zip_path, 'r') as zip_ref:
zip_ref.extractall(temp_extracted_folder)
# Replace the current JavaScript folder with the new one
new_javascript_folder = os.path.join(temp_extracted_folder, "ComfyUI-Assistant-main", "javascript")
# Replace the current JavaScript folder with the new one
new_javascript_folder = os.path.join(temp_extracted_folder, "ComfyUI-Assistant-main", "javascript")
# Copy the contents of the new JavaScript folder to the current folder
shutil.rmtree(javascript_folder)
shutil.copytree(new_javascript_folder, javascript_folder)
# Copy the contents of the new JavaScript folder to the current folder
shutil.rmtree(javascript_folder)
shutil.copytree(new_javascript_folder, javascript_folder)
# Cleanup: remove temporary files and folders
os.remove(temp_zip_path)
shutil.rmtree(temp_extracted_folder)
# Cleanup: remove temporary files and folders
os.remove(temp_zip_path)
shutil.rmtree(temp_extracted_folder)
transform_files_in_folder(javascript_folder)
WEB_DIRECTORY = 'javascript'
NODE_CLASS_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS = {}
+27
View File
@@ -0,0 +1,27 @@
import { app } from "../../scripts/app.js";
import * as data from './data.js';
window.data = data;
const ext = {
// Unique name for the extension
name: "ComfyUI-Assistant",
async setup(app) {
const menuLoadDefault = document.querySelector("#comfy-load-default-button");
const learnBtn = document.createElement("button");
learnBtn.textContent = "Learn";
if(!localStorage.getItem("CLICKED_LEARN")) {
learnBtn.classList.toggle("animate-background")
learnBtn.addEventListener("click", ()=>{
localStorage.setItem("CLICKED_LEARN","true")
learnBtn.classList.remove("animate-background")
})
}
learnBtn.addEventListener("click", ()=>{
window.onLearnClick()
})
menuLoadDefault.after(learnBtn);
},
};
app.registerExtension(ext);
+309
View File
@@ -0,0 +1,309 @@
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
.fixed {
position: fixed
}
.absolute {
position: absolute
}
.relative {
position: relative
}
.inset-0 {
inset: 0px
}
.left-0 {
left: 0px
}
.top-0 {
top: 0px
}
.z-50 {
z-index: 50
}
.m-4 {
margin: 1rem
}
.flex {
display: flex
}
.h-8 {
height: 2rem
}
.max-h-96 {
max-height: 24rem
}
.w-14 {
width: 3.5rem
}
.w-fit {
width: -moz-fit-content;
width: fit-content
}
.w-full {
width: 100%
}
.w-screen {
width: 100vw
}
.max-w-4xl {
max-width: 56rem
}
.cursor-pointer {
cursor: pointer
}
.flex-row {
flex-direction: row
}
.flex-col {
flex-direction: column
}
.items-center {
align-items: center
}
.justify-center {
justify-content: center
}
.justify-around {
justify-content: space-around
}
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)))
}
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse))
}
.overflow-y-auto {
overflow-y: auto
}
.rounded-xl {
border-radius: 0.75rem
}
.rounded-t-xl {
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem
}
.bg-comfy-light {
--tw-bg-opacity: 1;
background-color: rgb(53 53 53 / var(--tw-bg-opacity))
}
.bg-gray-500 {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity))
}
.object-cover {
-o-object-fit: cover;
object-fit: cover
}
.p-2 {
padding: 0.5rem
}
.px-1 {
padding-left: 0.25rem;
padding-right: 0.25rem
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem
}
.text-2xl {
font-size: 1.5rem;
line-height: 2rem
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem
}
.font-semibold {
font-weight: 600
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity))
}
.underline {
text-decoration-line: underline
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
}
@keyframes Gradient {
0%{
background-position: 0% 50%
}
50%{
background-position: 100% 50%
}
100%{
background-position: 0% 50%
}
}
.animated-background{
background: linear-gradient(270deg, #d53369, #daae51);
background-size: 200% 200%;
animation: Gradient 2s ease infinite;
}
.hover\:bg-gray-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity))
}
+314
View File
@@ -0,0 +1,314 @@
var docStyle = document.createElement('style');
docStyle.innerHTML = `*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
.fixed {
position: fixed
}
.absolute {
position: absolute
}
.relative {
position: relative
}
.inset-0 {
inset: 0px
}
.left-0 {
left: 0px
}
.top-0 {
top: 0px
}
.z-50 {
z-index: 50
}
.m-4 {
margin: 1rem
}
.flex {
display: flex
}
.h-8 {
height: 2rem
}
.max-h-96 {
max-height: 24rem
}
.w-14 {
width: 3.5rem
}
.w-fit {
width: -moz-fit-content;
width: fit-content
}
.w-full {
width: 100%
}
.w-screen {
width: 100vw
}
.max-w-4xl {
max-width: 56rem
}
.cursor-pointer {
cursor: pointer
}
.flex-row {
flex-direction: row
}
.flex-col {
flex-direction: column
}
.items-center {
align-items: center
}
.justify-center {
justify-content: center
}
.justify-around {
justify-content: space-around
}
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)))
}
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse))
}
.overflow-y-auto {
overflow-y: auto
}
.rounded-xl {
border-radius: 0.75rem
}
.rounded-t-xl {
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem
}
.bg-comfy-light {
--tw-bg-opacity: 1;
background-color: rgb(53 53 53 / var(--tw-bg-opacity))
}
.bg-gray-500 {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity))
}
.object-cover {
-o-object-fit: cover;
object-fit: cover
}
.p-2 {
padding: 0.5rem
}
.px-1 {
padding-left: 0.25rem;
padding-right: 0.25rem
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem
}
.text-2xl {
font-size: 1.5rem;
line-height: 2rem
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem
}
.font-semibold {
font-weight: 600
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity))
}
.underline {
text-decoration-line: underline
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
}
@keyframes Gradient {
0%{
background-position: 0% 50%
}
50%{
background-position: 100% 50%
}
100%{
background-position: 0% 50%
}
}
.animated-background{
background: linear-gradient(270deg, #d53369, #daae51);
background-size: 200% 200%;
animation: Gradient 2s ease infinite;
}
.hover\\:bg-gray-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity))
}
`;
document.head.appendChild(docStyle);
File diff suppressed because one or more lines are too long
-52
View File
@@ -1,52 +0,0 @@
import { app } from "../../scripts/app.js";
import {LearnModal} from './learn-menu.js'
import {latestVersion} from "./data.js";
const localVersion = 1;
var docStyle = document.createElement('style');
docStyle.innerHTML = `
@keyframes Gradient {
0%{background-position: 0% 50%}
50%{background-position: 100% 50%}
100%{background-position: 0% 50%}
}
`;
document.head.appendChild(docStyle);
let learnModalInstance = null;
const ext = {
// Unique name for the extension
name: "ComfyUI-Assistant",
async setup(app) {
const menuLoadDefault = document.querySelector("#comfy-load-default-button");
const learnBtn = document.createElement("button");
learnBtn.textContent = "Learn";
if(!localStorage.getItem("clickedLearn")) {
learnBtn.style.background = "linear-gradient(270deg, #d53369, #daae51)";
learnBtn.style.backgroundSize = "200% 200%";
learnBtn.style.animation = "Gradient 2s ease infinite";
learnBtn.addEventListener("click", ()=>{
localStorage.setItem("clickedLearn","true")
learnBtn.style=null;
})
}
learnBtn.addEventListener("click", ()=>{
if(latestVersion>localVersion){
alert("You are using an old version of the plugin, update it to get the latest features")
}
LearnModal.get().show();
})
menuLoadDefault.after(learnBtn);
},
};
app.registerExtension(ext);
+27967
View File
File diff suppressed because one or more lines are too long
-115
View File
@@ -1,115 +0,0 @@
const tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
let player;
const setVideo = (videoId)=> {
console.log(videoId)
player = new YT.Player('player',{
videoId: videoId,
events: {
'onStateChange': onPlayerStateChange
}
});
}
var done = false;
var lastInterval = null;
let keyframesFunctions= {}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
lastInterval = setInterval(function () {
// keyframesFunctions contains seconds and functions like {5:()=>console.log("five seconds!")} I want that this will always call the appropriate function based on the time but still taking to considerations interval hiccups
const currentTime = player.getCurrentTime();
const timeInSeconds = Math.floor(currentTime);
if (keyframesFunctions[timeInSeconds]) {
keyframesFunctions[timeInSeconds]();
}
}, 1000);
}
}
export function startVideo(title,videoId, _keyframesFunctions){
keyframesFunctions = _keyframesFunctions
const lastContainer = document.getElementById("youtube-container")
if(lastContainer){
lastContainer.remove()
clearInterval(lastInterval)
}
const ytContainer = document.createElement('div');
ytContainer.style.position="absolute"
ytContainer.style.top="50px"
ytContainer.style.left="50px"
ytContainer.style.zIndex="101"
ytContainer.setAttribute("id","youtube-container")
const videoContainerWindow = document.createElement('div');
videoContainerWindow.style.width="100%"
videoContainerWindow.style.height="30px"
videoContainerWindow.style.background="#5e5e5e"
videoContainerWindow.style.cursor="move";
videoContainerWindow.style.display= "flex";
videoContainerWindow.style.alignItems= "center";
const titleEl = document.createElement('span')
titleEl.style.flexGrow= "1";
titleEl.style.padding= "4px";
titleEl.appendChild(document.createTextNode(title))
videoContainerWindow.appendChild(titleEl);
//Add minimize and exit:
const minimizeButton = document.createElement('button');
minimizeButton.style.marginRight = "5px";
minimizeButton.innerHTML = "-";
minimizeButton.onclick = () => {
document.getElementById("player").hidden=!document.getElementById("player").hidden
}
const exitButton = document.createElement('button');
exitButton.innerHTML = "X";
exitButton.style.marginRight="5px";
exitButton.onclick = () => {
ytContainer.remove();
}
videoContainerWindow.appendChild(minimizeButton);
videoContainerWindow.appendChild(exitButton);
let drag = {x: 0, y: 0};
let dragging = false;
videoContainerWindow.onmousedown = (e) => {
drag.x = e.clientX - ytContainer.offsetLeft;
drag.y = e.clientY - ytContainer.offsetTop;
dragging=true
}
document.onmousemove = (e) => {
if (e.buttons === 1 && dragging) {
ytContainer.style.left = `${e.clientX - drag.x}px`;
ytContainer.style.top = `${e.clientY - drag.y}px`;
}
}
document.onmouseup = (e) => {
drag = {x: 0, y: 0};
dragging=false;
}
ytContainer.appendChild(videoContainerWindow)
const ytPlayer = document.createElement('div');
ytPlayer.setAttribute("id","player")
ytContainer.appendChild(ytPlayer)
document.body.appendChild(ytContainer);
setVideo(videoId)
}
+2202
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
{
"name": "ui",
"private": true,
"version": "1.0.0",
"scripts": {
"build:esbuild": "esbuild src/index.jsx --bundle --outfile=../javascript/out.js --loader:.png=dataurl",
"build:css": "npx tailwindcss -i ./src/global.css -o ../javascript/global.css --minify",
"build": "npm-run-all --parallel build:*",
"watch:esbuild": "esbuild src/index.jsx --bundle --watch --outfile=../javascript/out.js --loader:.png=dataurl",
"watch:css": "npx tailwindcss -i ./src/global.css -o ../javascript/global.css --watch",
"dev": "npm-run-all --parallel watch:*"
},
"devDependencies": {
"esbuild": "0.19.11",
"tailwindcss": "^3.4.0",
"npm-run-all": "^4.1.5"
},
"dependencies": {
"@headlessui/react": "^1.7.17",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-draggable": "^4.4.6",
"react-youtube": "^10.1.0"
}
}
+29
View File
@@ -0,0 +1,29 @@
import React, { useState } from 'react';
import { Dialog } from '@headlessui/react'
import logo from './logo.png';
import LearnDialog from "./LearnDialog";
import YoutubePlayer from "./YoutubePlayer";
const ComfyAssistantOverlay = () => {
const [isOpen,setIsOpen] = useState(false)
const [video,setVideo] = useState(null)
window.onLearnClick = () => {
setIsOpen(true)
}
return (
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
className="relative z-50"
>
{!video && <LearnDialog close={()=>setIsOpen(false)} startVideo={(video) => setVideo(video)}/>}
{video && <YoutubePlayer videoId={'BT2Kpm1cU-w'} close={()=> {
setIsOpen(false)
setVideo(null)
}} />}
</Dialog>
);
};
export default ComfyAssistantOverlay;
+82
View File
@@ -0,0 +1,82 @@
import React, {useState} from 'react';
import {Dialog} from "@headlessui/react";
import logo from "./logo.png";
import Draggable from "react-draggable";
// moduleItem.querySelector('button').addEventListener('click', () => {
// LearnModal.get().close()
// if(module.initialWorkflow){
// app.loadGraphData(JSON.parse(module.initialWorkflow))
// }
// if(module.type === 'lesson') {
// const keyframesFunctions = {}
// if(module.keyframesWorkflows){
// for (let keyframe in module.keyframesWorkflows) {
// const parsedWorkflow = JSON.parse(module.keyframesWorkflows[keyframe])
// keyframesFunctions[keyframe] = ()=> app.loadGraphData(parsedWorkflow);
// }
// }
// startVideo(module.title,module.videoId,keyframesFunctions)
// }
function LearnDialog({close, startVideo}) {
const [selectedCategory,setSelectedCategory] = useState(window.data.categories[0])
return (
<Draggable>
<div className="fixed inset-0 flex w-screen items-center justify-center p-2">
<Dialog.Panel className="w-full max-w-4xl rounded-xl bg-comfy-light px-4 relative">
<span className={"font-semibold absolute top-0 left-0 m-4 cursor-pointer"}
onClick={close}>X</span>
<Dialog.Title className={"flex flex-row justify-center"}>Comfy Assistant <span
className={"px-2 text-xs"}>by <a
href={"https://openart.ai"}><img src={logo} className={"w-14 px-1"}/></a></span>
</Dialog.Title>
<div className={"flex flex-col"}>
<div className="flex flex-row justify-around underline space-x-2 p-2">
{window.data.categories.map(cat => <a key={cat} className={"cursor-pointer"}
onClick={() => {
setSelectedCategory(cat)
}}>{cat}</a>)}
</div>
<div className={"flex flex-col max-h-96 overflow-y-auto space-y-2 p-2 "}>
{window.data.modules.filter(module => module.categories.includes(selectedCategory)).map(module =>
<div key={module.title}
className={"flex items-center flex-row space-x-2 p-2 hover:bg-gray-500 cursor-pointer"}
onClick={(e) => {
if (module.initialWorkflow) {
app.loadGraphData(JSON.parse(module.initialWorkflow))
}
if (module.type === 'lesson') {
const keyframesFunctions = {}
if (module.keyframesWorkflows) {
for (let keyframe in module.keyframesWorkflows) {
const parsedWorkflow = JSON.parse(module.keyframesWorkflows[keyframe])
keyframesFunctions[keyframe] = () => app.loadGraphData(parsedWorkflow);
}
}
startVideo({title:module.title, videoId:module.videoId, keyframesFunctions})
} else {
close()
}
}}
>
<img width={96} height={96} className={"object-cover"}
src={module.thumbnail ? module.thumbnail : `https://img.youtube.com/vi/${module.videoId}/default.jpg`}/>
<div className={"flex flex-col"}>
<span className={"font-semibold text-2xl py-2"}>{module.title}</span>
<span className={"text-sm text-gray-300"}>{module.description}</span>
<hr/>
</div>
</div>)}
</div>
</div>
</Dialog.Panel>
</div>
</Draggable>
);
}
export default LearnDialog;
+51
View File
@@ -0,0 +1,51 @@
import React, {useEffect, useRef, useState} from 'react';
import YouTube from 'react-youtube';
import {Dialog} from "@headlessui/react";
import Draggable from "react-draggable";
function YoutubePlayer({videoId,close,keyframesFunctions}) {
const playerStateRef= useRef(-1)
const playerRef= useRef(null)
const onPlayerStateChange = (event) => {
playerRef.current = event.target
playerStateRef.current = event.data
}
useEffect(() => {
const lastInterval = setInterval(function () {
// keyframesFunctions contains seconds and functions like {5:()=>console.log("five seconds!")} I want that this will always call the appropriate function based on the time but still taking to considerations interval hiccups
const currentTime = playerRef.current.getCurrentTime();
const timeInSeconds = Math.floor(currentTime);
if (keyframesFunctions[timeInSeconds]) {
keyframesFunctions[timeInSeconds]();
}
}, 1000);
return () => {
clearInterval(lastInterval)
}
}, []);
return (
<Draggable>
<div className="fixed inset-0 flex w-screen items-center justify-center p-2" >
<Dialog.Panel className="w-fit max-w-4xl rounded-xl bg-comfy-light relative">
<div className={"flex flex-row items-center font-semibold w-full bg-gray-500 top-0 left-0 h-8 rounded-t-xl"}>
<span className={"cursor-pointer px-2"} onClick={close}>X</span>
</div>
<div className={""}>
<YouTube videoId={videoId} onPlayerStateChange={onPlayerStateChange}/>
</div>
</Dialog.Panel>
</div>
</Draggable>
)
;
}
export default YoutubePlayer;
+16
View File
@@ -0,0 +1,16 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@keyframes Gradient {
0%{background-position: 0% 50%}
50%{background-position: 100% 50%}
100%{background-position: 0% 50%}
}
.animated-background{
background: linear-gradient(270deg, #d53369, #daae51);
background-size: 200% 200%;
animation: Gradient 2s ease infinite;
}
+8
View File
@@ -0,0 +1,8 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import ComfyAssistantOverlay from "./ComfyAssistantOverlay";
const rootDomNode = document.createElement('div');
document.body.appendChild(rootDomNode);
const root = ReactDOM.createRoot(rootDomNode);
root.render(<ComfyAssistantOverlay />);
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+17
View File
@@ -0,0 +1,17 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{ts,js,jsx,tsx}"],
theme: {
extend: {
colors:{
"comfy-light":"#353535",
"comfy-dark":"#222222",
}
},
},
plugins: [],
corePlugins:{
preflight:false
}
}