feat: add antd token support

pull/23/head
canisminor1990 2023-02-25 14:42:18 +08:00
commit 6c712233be
15 changed files with 3519 additions and 0 deletions

32
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,32 @@
on:
schedule:
# runs once a week on sunday
- cron: "55 23 * * 0"
jobs:
# This workflow contains a single job called "traffic"
traffic:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
with:
ref: "traffic"
# Calculates traffic and clones and stores in CSV file
- name: GitHub traffic
uses: sangonzal/repository-traffic-action@v.0.1.6
env:
TRAFFIC_ACTION_TOKEN: ${{ secrets.TRAFFIC_ACTION_TOKEN }}
# Commits files to repository
- name: Commit changes
uses: EndBug/add-and-commit@v4
with:
author_name: Gerschel
message: "GitHub traffic"
add: "./traffic/*"
ref: "traffic" # commits to branch "traffic"

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
**/node_modules
npm-debug.log*
yarn-error.log
package-lock.json
# production
**/dist
/plugins/
/es
/lib
/logs
# misc
.DS_Store
.eslintcache
.husky
# umi
/src/.umi
/src/.umi-production
/src/.umi-test
/.env.local
# ide
.idea
.vscode
.history
*.log
functions/*
lambda/mock/index.js
.temp/**
# test
**/test-output
config.yml

View File

View File

58
javascript/background.js Normal file
View File

@ -0,0 +1,58 @@
class InjectBackground{
constructor(){
this.image;
}
async init(selector="div[class^=mx-auto][class*=container]"){
this.element = undefined
while(true){
this.element = gradioApp().querySelector(selector)
if (this.element){
break
}
await delay(500)
}
this.element.setAttribute("style", "background-image: url(file=static/background.png); background-size: contain; background-attachment: fixed; background-position: center; background-repeat: no-repeat")
}
removeStyle(){
this.element.removeStyle()
}
removeImage(){
this.element.style['background-image'] = ""
}
updateImage(path){
this.element.style['background-image'] = `url(file=${path})`
}
//destroy not necessarily needed at this time, it's to keep the api similar
destroy(){
this.removeStyle()
}
async refreshImage(file_name){
setTimeout(location.reload(), 200)
//this.updateImage("static/background.png")
console.log(file_name)
return file_name
}
}
/*
element.style {
background-image: url(file=logo.png);
background-size: cover;
background-attachment: fixed;
background-position: center;
}
*/
let injectBackground = new InjectBackground()
async function registerInjectHandler(){
await injectBackground.init()
while(true){
if(injectBackground.element){
break
}
await delay(500)
}
qkcssImagemap.injectBackground = injectBackground
}
function delay(ms){return new Promise(resolve => setTimeout(resolve, ms))}
document.addEventListener("DOMContentLoaded", async function (){await registerInjectHandler()})

22
javascript/favicon.js Normal file
View File

@ -0,0 +1,22 @@
class FaviconHandler {
static setFavicon() {
const link = document.createElement('link');
link.rel = 'icon';
link.type = 'image/svg+xml';
link.href = getComputedStyle(gradioApp().querySelector('.icon-container')).backgroundImage.replace(/^url\("|"\)$/g, '');
document.getElementsByTagName('head')[0].appendChild(link);
}
static observeGradioApp() {
const observer = new MutationObserver(() => {
const iconContainer = gradioApp().querySelector('.icon-container');
if (iconContainer) {
observer.disconnect();
FaviconHandler.setFavicon();
}
});
observer.observe(gradioApp(), { childList: true, subtree: true });
}
}
document.addEventListener("DOMContentLoaded", () => {
FaviconHandler.observeGradioApp();
});

100
javascript/matrixfx.js Normal file
View File

@ -0,0 +1,100 @@
class MatrixEffect{
constructor(){
this.matrixCanvas = document.createElement("canvas")
this.matrixCanvas.setAttribute("style", "position: fixed;")
gradioApp().querySelector("div[class*=container]:not([class^=modal])").insertAdjacentElement('afterbegin', this.matrixCanvas)
}
async initialize(){
while(!gradioApp().querySelector('canvas')){
await delay(300)
}
// Initialising the canvas
this.ctx = this.matrixCanvas.getContext('2d');
// Setting the width and height of the canvas
this.matrixCanvas.width = window.innerWidth;
this.matrixCanvas.height = window.innerHeight;
// Setting up the letters
this.letters = 'ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ';
this.letters = this.letters.split('');
// Setting up the columns
this.fontSize = 10,
this.columns = this.matrixCanvas.width / this.fontSize;
// Setting up the drops
this.drops = [];
for (var i = 0; i < this.columns; i++) {
this.drops[i] = 1;
}
this.running = true;
//timer
this.then = Date.now();
this.fps = 20;
this.fpsInterval = 1000/this.fps;
// Setting up the draw function
this.draw = () => {
this.now = Date.now();
this.elapsed = this.now - this.then;
if (this.elapsed > this.fpsInterval){
this.then = this.now - (this.elapsed % this.fpsInterval);
this.ctx.fillStyle = 'rgba(0, 0, 0, .1)';
this.ctx.fillRect(0, 0, this.matrixCanvas.width, this.matrixCanvas.height);
for (var i = 0; i < this.drops.length; i++) {
text = this.letters[Math.floor(Math.random() * this.letters.length)];
this.ctx.fillStyle = '#0f0';
this.ctx.fillText(text, i * this.fontSize, this.drops[i] * this.fontSize);
this.drops[i]++;
if (this.drops[i] * this.fontSize > this.matrixCanvas.height && Math.random() > .95) {
this.drops[i] = 0;
}
}
}
if (this.running){
requestAnimationFrame(this.draw)
}
}
}
destroy(){
this.running = false;
//clearInterval(this.Interval)
this.matrixCanvas.remove()
}
}
let matrixEffect;
async function registerMatrixToHandler(){
await delay(1000);
while(qkcssFXMap == undefined){
await delay(500)
}
qkcssFXMap["matrixfx"] = [launchMatrixEffect, matrixEffect];
}
async function launchMatrixEffect(){
await delay(1000)
while (!gradioApp().querySelector("div[class*=container]:not([class^=modal])")){
await delay(300);
}
// Loop the animation
matrixEffect = new MatrixEffect()
//Shortciruited it
qkcssFXMap["matrixfx"][1] = matrixEffect
await delay(500)
matrixEffect.initialize()
matrixEffect.Interval = matrixEffect.draw();
//matrixEffect.Interval = setInterval(matrixEffect.draw, 33);
}
function delay(ms){return new Promise(resolve => setTimeout(resolve, ms))}
//document.addEventListener("DOMContentLoaded", async function() {await launchMatrixEffect()})
document.addEventListener("DOMContentLoaded", async function() {await registerMatrixToHandler()})

72
javascript/quickcss.js Normal file
View File

@ -0,0 +1,72 @@
function quickcssFormatRule(val, ele, colorsSize){
//async is not needed, just trying to debug some error from colorpicker
ele = parseInt(ele)
//get sheet from style tag
let quickcssSheet = document.documentElement.querySelector("gradio-app").shadowRoot.querySelector("style").sheet
//get it's rules
let quickcssCssr = quickcssSheet.cssRules
//convert to array for finding index
let quickcssCssrArray = Array.from(quickcssCssr)
//use custom target to find index
let quickcssTarget = quickcssCssrArray.find( item => item.cssText.includes("quickcss_target"))
let quickcssTargetIndex = quickcssCssrArray.indexOf(quickcssTarget)
//Pull rule out
let quickcssRuleAsString = quickcssCssr[quickcssTargetIndex].cssText.toString()
//splitter for rule targets and body
let ruleSplitIndex = quickcssRuleAsString.indexOf("{")
//Target of rule
let ruleTargets = quickcssRuleAsString.slice(0, ruleSplitIndex)
//Body of rule
let quickcssRuleBody = quickcssRuleAsString.slice(ruleSplitIndex)
//Rule body edit
let asSplit = quickcssRuleBody.split(";")
let endStr = asSplit.slice(parseInt(colorsSize)).join(";")
//Edit to element position, index and length given as string via hiddenvals components
while (asSplit.length > parseInt(colorsSize))
{
asSplit.pop()
}
let asArray = new Array
asSplit.forEach( e => {asArray.push(e.split(":"))})
let stringarray = new Array
asArray.forEach( (e, i) => {stringarray.push( i==ele ? `${e[0]}: ${val}`: `${e[0]}: ${e[1]}`)})
stringarray = stringarray.join(";") + `;${endStr}`
let cssRule = ruleTargets + stringarray
//Delete old rule at
quickcssSheet.deleteRule(quickcssTargetIndex)
//insert (as in add at same location)
quickcssSheet.insertRule(cssRule, quickcssTargetIndex)
//returns must equal inputs size, so outputs must matchsize, python fn hijacks for finishing save data
return [stringarray, "", ""]
}
//Register js fx's
//they must support a destroy method
qkcssFXMap = {};
function launchEffect(filename){
qkcssFXMap[filename][0]()
}
function destroyEffect(filename){
qkcssFXMap[filename][1].destroy()
}
//Register js image injectors
qkcssImagemap = {};
function launchImage(name){
qkcssImagemap[name].register()
}
function removeImage(name){
qkcssImagemap[name].destroy()
}
function updateImage(name, new_name){
//notimplemented hidden component to send name?
qkcssImagemap[name].updateImage(new_name)
}
async function refreshImage(name){
await qkcssImagemap[name].refreshImage()
return name
}

0
logos/Put logos here.txt Normal file
View File

Binary file not shown.

Binary file not shown.

387
scripts/quickcss.py Normal file
View File

@ -0,0 +1,387 @@
import gradio as gr
import modules.scripts as scripts
from modules import script_callbacks, shared
import os
import shutil
from pathlib import Path
basedir = scripts.basedir()
class MyTab():
def __init__(self, basedir):
#This extensions directory
self.extensiondir = basedir
#Up two directories, webui root
self.webui_dir = Path(self.extensiondir).parents[1]
self.style_folder = os.path.join(basedir, "style_choices")
self.backgrounds_folder = os.path.join(self.extensiondir, "backgrounds")
self.logos_folder = os.path.join(self.extensiondir, "logos")
self.favicon_folder = os.path.join(self.extensiondir, "favicons")
self.effects_folder = os.path.join(self.extensiondir, "effects")
self.javascript_folder = os.path.join(self.extensiondir, "javascript")
self.static_folder = os.path.join(self.webui_dir, "static")
self.favicon_workaround = gr.HTML(value='<div class="icon-container"></div>', render=False)
self.styles_list = self.get_files(self.style_folder)
self.backgrounds_list = self.get_files(self.backgrounds_folder)
self.logos_list = self.get_files(self.logos_folder)
self.favicon_list = self.get_files(self.favicon_folder)
self.effects_list = self.get_files(self.javascript_folder, file_filter=["quickcss.js", "utility.js", "background.js"], split=True)
self.styles_dropdown = gr.Dropdown(label="Styles", render=False, interactive=True, choices=self.styles_list, type="value")
self.background_dropdown = gr.Dropdown(label="Background", render=False, interactive=True, choices=self.backgrounds_list, type="value")
self.logos_dropdown = gr.Dropdown(label="Logos", render=False, interactive=True, choices=self.logos_list, type="value")
self.favicon_dropdown = gr.Dropdown(label="Favicon", render=False, interactive=True, choices=self.favicon_list, type="value")
self.effects_dropdown = gr.Dropdown(label="Effects (on until refresh)", render=False, interactive=True, choices=self.effects_list, type="value")
self.apply_style_bttn = gr.Button(value="Apply Style", render=False)
self.apply_background_bttn = gr.Button(value="Apply (Reload UI)", render=False)
#TODO: background off button to swap image in folder to blankbackground and disable style rule
self.refresh_bkcgrnd_droplist_button = gr.Button(value="Refresh List", render=False)
self.apply_logo_bttn = gr.Button(value="Apply Logo", render=False)
self.apply_favicon_bttn = gr.Button(value="Apply Favicon (edit webui.py to see)", render=False)
self.effects_button = gr.Button(value="Activate Selected Script", render=False)
self.effects_off_button = gr.Button(value="Deactivate Selected Script", render=False)
self.logo_image = gr.Image(render=False)
self.favicon_image = gr.Image(render=False)
self.import_style_file = gr.File(render=False, label="Import CSS file")
self.import_background_file = gr.File(render=False, label="Import Background Images")
self.import_logo_file = gr.File(render=False, label="Import Logo's (png)")
self.import_favicon_file = gr.File(render=False, label="Import favicons (svg)")
self.restart_bttn = gr.Button(value="Apply changes (Reload UI)", render=False, variant="primary")
self.remove_style = gr.Button(value="Remove Stylesheet", render=False)
# BEGIN CSS COLORPICK COMPONENTS
self.save_as_filename = gr.Text(label="Save Name", visible=False, render=False)
self.save_button = gr.Button(value="Save", visible=False, render=False, variant="primary")
#Test for file being set
self.file_exists = False
self.style_path = os.path.join(self.extensiondir, "style.css")
self.start_position_for_save = 0
self.insert_colorpicker_break_rule_for_save = 0
self.insert_break_rule_for_save = 0
if os.path.exists(self.style_path):
self.file_exists = True #Conditional for creating inputs
self.lines = []
line = ""
self.dynamic_compatible = False
with open(self.style_path, 'r', encoding='utf-8') as cssfile:
try:
for i, line in enumerate(cssfile):
line = line.strip()
if "/*BREAKFILEREADER*/" in line:
self.insert_break_rule_for_save = i - self.start_position_for_save
break
elif "/*ENDCOLORPICKERS*/" in line:
self.insert_colorpicker_break_rule_for_save = i - self.start_position_for_save
continue
if "quickcss_target" in line:
self.dynamic_compatible = True
self.start_position_for_save = i+1
continue
if self.dynamic_compatible:
if len(line) > 0:
self.lines.append(line.split(":"))
except UnicodeDecodeError as error:
print(f"{error}\nCheck style.css in this extensions folder.")
if self.dynamic_compatible:
self.dynamically_generated_components = [gr.ColorPicker(label=x[0].replace("-", "").replace("_", " ").title(), render=False, elem_id="quikcss_colorpicker", value=x[1].replace(";", "").strip())
if i < self.insert_colorpicker_break_rule_for_save else
gr.Slider(minimum=0, maximum=100, step=1, label=x[0].replace("-", "").replace("_", " ").title(), render=False, elem_id="quikcss_slider", value=x[1].replace(";", "").strip())
for i,x in enumerate(self.lines)
]
else:
self.dynamically_generated_components = []
# hidden_vals acts like an index, holds int values that are used in js
self.hidden_vals = [gr.Text(value=str(x), render=False, visible=False) for x in range(len(self.dynamically_generated_components))]
# length_of_colors similar to hidden vals, but provides length so js knows the limit when parsing rules
self.length_of_colors = gr.Text(value=len(self.dynamically_generated_components), visible=False, render=False)
# used as padding so we don't list index error or http 500 internal server, or http 422 forEach can't over undefined (promise pending)
self.dummy_picker = gr.Text(visible=False, render=False, elem_id="hidden")
# Acts like catcher, actual values store in list
self.js_result_component = gr.Text(render=False, interactive=False)
#dummy component for general purpose, currently used for _js effects; holds no relevant data, just for input/output element quota
self._dummy = gr.Text(value="", visible=False, render=False, show_label=False, interactive=False)
def ui(self, *args, **kwargs):
with gr.Blocks(analytics_enabled=False) as ui:
self.favicon_workaround.render()
with gr.Accordion(label="Some instructions", open=False):
gr.Markdown(value="""<center>This is a mix from old style to new style. It is not in it's finished state</center>
<center>To see effects, you must use dropdown, select as sheet, click apply, click restart. More options will be available on restart</center>
<center>I know it lives as a tab, but this was meant to be a demo at first, now it's growing to something more</center>
<center>To see favicon take affect, you will need to add `favicon_path="favicon.svg"` to webui.py</center>
<center>To do this, open file, search for `prevent_thread_lock` add comma, paste in text, save.</center>
<center>You may need to undo this for an update, if you have git issues and don't know how to deal with them</center>
<center>This won't break your system, if you find you can't update, try `git checkout webui.py` ~~`git fetch --all` `git reset --hard origin/master`~~</center>
<center>Once again, this `dynamic` demo has not removed/re-implemented all features present</center>
""")
if self.file_exists and self.dynamic_compatible:
with gr.Row(equal_height=True):
self.save_as_filename.render()
self.save_button.render()
#Necessary for values being accessible
self.length_of_colors.render()
self.dummy_picker.render()
self.js_result_component.render()
#Render hidden vals that serve as indices to map
for h in self.hidden_vals:
h.render()
with gr.Row():
#Render adjusters
for c in self.dynamically_generated_components:
with gr.Column(elem_id="quickcss_colorpicker"):
c.render()
with gr.Row():
with gr.Column():
self.styles_dropdown.render()
self.apply_style_bttn.render()
with gr.Column():
self.background_dropdown.render()
with gr.Row():
self.apply_background_bttn.render()
self.refresh_bkcgrnd_droplist_button.render()
with gr.Column():
self.logos_dropdown.render()
self.apply_logo_bttn.render()
with gr.Column():
self.favicon_dropdown.render()
self.apply_favicon_bttn.render()
with gr.Column():
self.effects_dropdown.render()
with gr.Row():
self.effects_button.render()
self.effects_off_button.render()
with gr.Accordion(label="Import Files", open=False):
with gr.Row():
with gr.Column():
self.import_style_file.render()
with gr.Column():
self.import_background_file.render()
with gr.Column():
self.import_logo_file.render()
with gr.Column():
self.import_favicon_file.render()
with gr.Row():
self.restart_bttn.render()
self.remove_style.render()
with gr.Row():
self.logo_image.render()
self.favicon_image.render()
self._dummy.render()
# Handlers
#Generate colorpickers and sliders handlers
if self.file_exists:
for comp,val in zip(self.dynamically_generated_components, self.hidden_vals):
comp.change(
fn = lambda *x: self.process_for_save(*x),
_js = "quickcssFormatRule",
inputs = [comp, val, self.length_of_colors],
outputs = [self.js_result_component] + [self.save_as_filename, self.dummy_picker]
)
self.save_as_filename.change(
fn = lambda x: gr.update(visible=bool(x)),
inputs = self.save_as_filename,
outputs = self.save_button
)
self.save_button.click(
fn = self.save,
inputs = [self.js_result_component, self.save_as_filename],
outputs = [self.js_result_component, self.styles_dropdown]
)
#Handler cont.
#Common interface
#NOTE: These dropdowns affect image placeholders
self.logos_dropdown.change(
fn = lambda x: self.get_image(x, folder = "logos"),
inputs = self.logos_dropdown,
outputs = self.logo_image
)
self.favicon_dropdown.change(
fn = lambda x: self.get_image(x, folder = "favicons"),
inputs = self.favicon_dropdown,
outputs = self.favicon_image
)
#buttons
self.apply_style_bttn.click(
fn = self.apply_choice_wrapper(self.style_folder, self.extensiondir, "style.css"),
inputs = self.styles_dropdown
)
self.apply_background_bttn.click(
fn = self.apply_choice_wrapper(self.backgrounds_folder, self.static_folder, "background.png"),#TODO: MAYBE: delete file extension
_js = "injectBackground.refreshImage",
inputs = self.background_dropdown,
outputs=self._dummy
)
self.refresh_bkcgrnd_droplist_button.click(
fn = lambda: self.refresh_list(self.refresh_bkcgrnd_droplist_button, self.backgrounds_folder, self.background_dropdown),
outputs=self.background_dropdown
)
self.apply_logo_bttn.click(
fn = self.apply_choice_wrapper(self.logos_folder, self.static_folder, "logo.png"),#TODO Update css files and change dir to static
inputs = self.logos_dropdown,
)
self.apply_favicon_bttn.click(
fn = self.apply_choice_wrapper(self.favicon_folder, self.static_folder, "favicon.svg"),#TODO update css files and change dir to static
inputs = self.favicon_dropdown
)
self.effects_button.click(
fn = None,
_js = "launchEffect",
inputs = self.effects_dropdown,
outputs = self._dummy
)
self.effects_off_button.click(
fn = None,
_js = "destroyEffect",
inputs = self.effects_dropdown,
outputs = self._dummy
)
self.remove_style.click(
fn = lambda: self.delete_style()
)
self.restart_bttn.click(fn=self.local_request_restart, _js='restart_reload', inputs=[], outputs=[])
#File Importers
self.import_style_file.change(
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="style_choices", comp = self.styles_dropdown, func = self.get_files, folder=self.style_folder, focus_list=self.styles_list),
inputs=self.import_style_file,
outputs=self.styles_dropdown
)
self.import_background_file.change(
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="backgrounds", comp = self.background_dropdown, func = self.get_files, folder=self.backgrounds_folder, focus_list=self.backgrounds_list),
inputs=self.import_background_file,
outputs=self.background_dropdown
)
self.import_logo_file.change(
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="logos", comp = self.logos_dropdown, func = self.get_files, folder=self.logos_folder, focus_list=self.logos_list),
inputs=self.import_logo_file,
outputs=self.logos_dropdown
)
self.import_favicon_file.change(
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="favicons", comp = self.favicon_dropdown, func = self.get_files, folder=self.favicon_folder, focus_list=self.favicon_list),
inputs=self.import_favicon_file,
outputs=self.favicon_dropdown
)
return [(ui, "Theme", "theme")]
def import_file_from_path(self, tmp_file_obj, target_folder, comp, func, **kwargs):
if tmp_file_obj:
shutil.copy(tmp_file_obj.name, os.path.join(self.extensiondir, target_folder, tmp_file_obj.orig_name))
# Update appropriate list
# Make backend the same as front-end so it matches when selected
comp.choices = func(**kwargs)
tmp_file_obj.flush()
# return sends update to front-end
return gr.update(choices=comp.choices)
def get_files(self, folder, focus_list=[], file_filter=[], split=False):
focus_list = [file_name if not split else os.path.splitext(file_name)[0] for file_name in os.listdir(folder) if os.path.isfile(os.path.join(folder, file_name)) and file_name not in file_filter]
return focus_list
def apply_choice_wrapper(self, src_base_path, dst_base_path, name):
"""Encapsulation so I don't need a different function for each type"""
def apply_choice(selection):
shutil.copy(os.path.join(src_base_path, selection), os.path.join(dst_base_path, name))
return apply_choice
def get_image(self, name, folder):
return os.path.join(self.extensiondir, folder, name)
def refresh_list(self, component, folder, focus_list, file_filter=[]):
component.choices = self.get_files(folder, focus_list, file_filter)
return gr.update(choices=component.choices)
def delete_style(self):
try:
os.remove(os.path.join(self.extensiondir, "style.css"))
except FileNotFoundError:
pass
def local_request_restart(self):
"Restart button"
shared.state.interrupt()
shared.state.need_restart = True
def process_for_save(self, x, *y):
return [x] + [gr.update(visible=True), None]
def save(self, js_cmp_val, filename):
rules = [f" {e};\n" for e in js_cmp_val[1:-1].split(";")][:-1]
#issue, save button needs to stay hidden until some color change
rules.insert(self.insert_colorpicker_break_rule_for_save, " /*ENDCOLORPICKERS*/\n")
rules.insert(self.insert_break_rule_for_save, " /*BREAKFILEREADER*/\n")
with open(self.style_path, 'r+') as file:
lines = file.readlines()
start_pos = self.start_position_for_save
for i, rule in enumerate(rules):
lines[start_pos + i] = rule
file.seek(0)
file.writelines(lines)
self.styles_dropdown.choices.insert(0, f"{filename}.css")
shutil.copy(self.style_path, os.path.join(self.style_folder, f"{filename}.css"))
return ["Saved", gr.update(choices=self.styles_dropdown.choices, value=self.styles_dropdown.choices[0])]
tab = MyTab(basedir)
script_callbacks.on_ui_tabs(tab.ui)

67
scripts/updater.py Normal file
View File

@ -0,0 +1,67 @@
from dataclasses import dataclass
import os
from pathlib import Path
import shutil
from modules import scripts
@dataclass
class DefaultFile:
"""Move file to location as filename"""
og_file:str
current_path:str
dir:str
save_as_filename:str
#class UpdateInstructions:
# @staticmethod
# def instructions(other_clss):
# #Create new folder
# in_root_folders = ["static"]
# #in_extension_folder = []
# for f_name in in_root_folders:
# other_clss.check_folder
class BasicUpdater:
def __init__(self):
#sd-web-ui-qkcss dir
self.extensions_dir = scripts.basedir()
self.root_dir = Path(self.extensions_dir).parents[1]
self.static_dir = os.path.join(self.root_dir, "static")
self.style_folder = os.path.join(self.extensions_dir, "style_choices")
self.logos_folder = os.path.join(self.extensions_dir, "logos")
self.favicon_folder = os.path.join(self.extensions_dir, "favicons")
self.backgrounds_folder = os.path.join(self.extensions_dir, "backgrounds")
self.effects_folder = os.path.join(self.extensions_dir, "effects")
self.javascript_folder = os.path.join(self.extensions_dir, "javascript")
self.file_defaults = [
DefaultFile(og_file="logo.png", current_path=self.logos_folder, dir=self.static_dir, save_as_filename="logo.png"),
DefaultFile(r"favicon Original.svg", self.favicon_folder, self.static_dir, "favicon.svg"),
DefaultFile("blankbackground.png", self.backgrounds_folder, self.static_dir, "background.png")
]
self.updater_file = os.path.join(self.extensions_dir, "update")
if os.path.exists(self.updater_file):
self.check_folders(self.static_dir)
for fd in self.file_defaults:
self.clone_file(fd)
#UpdateInstructions.instructions(self)
os.remove(self.updater_file)
def check_folders(self, folder_path):
if not os.path.exists(folder_path):
os.mkdir(folder_path)
def clone_file(self, defaults_object:DefaultFile):
from_file = os.path.join(defaults_object.current_path, defaults_object.og_file)
to_file = os.path.join(defaults_object.dir, defaults_object.save_as_filename)
if not os.path.exists(to_file):
shutil.copy(from_file, to_file)
BasicUpdater()

1371
style.css Normal file

File diff suppressed because it is too large Load Diff

1371
style_choices/style.css Normal file

File diff suppressed because it is too large Load Diff