From 876fc5946a9a21d5c2bd3a6a47ef1ef8a87b2e45 Mon Sep 17 00:00:00 2001 From: BomberFish Date: Mon, 2 Dec 2024 17:58:52 -0500 Subject: [PATCH 1/7] Merge Theme Editor and Wallpaper Selector --- src/Boot.tsx | 8 +- src/anura.css | 6 +- src/coreapps/ThemeEditor.tsx | 274 --------- src/coreapps/WallpaperSelector.tsx | 873 +++++++++++++++++++---------- 4 files changed, 598 insertions(+), 563 deletions(-) delete mode 100644 src/coreapps/ThemeEditor.tsx diff --git a/src/Boot.tsx b/src/Boot.tsx index b42d4cc8..4e3960f8 100644 --- a/src/Boot.tsx +++ b/src/Boot.tsx @@ -483,8 +483,8 @@ document.addEventListener("anura-login-completed", async () => { const wallpaper = new WallpaperSelector(); anura.registerApp(wallpaper); - const themeEditor = new ThemeEditor(); - anura.registerApp(themeEditor); + // const themeEditor = new ThemeEditor(); + // anura.registerApp(themeEditor); const explore = new ExploreApp(); anura.registerApp(explore); @@ -636,12 +636,12 @@ document.addEventListener("anura-login-completed", async () => { const desktopCtx = new ContextMenu(true); // we are init'ing before anura so this is needed desktopCtx.addItem( - "Set wallpaper", + "Set wallpaper & style", () => { // this however will execute after anura is init'ed anura.apps["anura.wallpaper"].open(); }, - "wallpaper", + "brush", ); document.addEventListener("contextmenu", function (e) { diff --git a/src/anura.css b/src/anura.css index b3ff186b..ad38c720 100755 --- a/src/anura.css +++ b/src/anura.css @@ -116,7 +116,8 @@ nav li { position: absolute; background-color: var(--theme-secondary-bg); padding: 5px 0; - width: 150px; + min-width: 150px; + max-width: 250px; box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); z-index: 10000; @@ -128,7 +129,8 @@ nav li { .custom-menu.large { padding: 5px 0; - width: 170px; + min-width: 170px; + max-width: 300px; background-color: color-mix(in srgb, var(--theme-dark-bg) 85%, transparent); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); diff --git a/src/coreapps/ThemeEditor.tsx b/src/coreapps/ThemeEditor.tsx deleted file mode 100644 index 7154f931..00000000 --- a/src/coreapps/ThemeEditor.tsx +++ /dev/null @@ -1,274 +0,0 @@ -class ThemeEditor extends App { - name = "Theme Editor"; - package = "anura.ui.themeeditor"; - icon = "/assets/icons/theme.png"; - - state = $state({ - resizing: false, - }); - - picker: any; - - css = css` - width: 100%; - height: 100%; - position: absolute; - overflow-y: auto; - - input[type="color"] { - appearance: none; - background: none; - padding: 0; - border: 0; - border-radius: 1rem; - width: 4rem; - height: 3rem; - } - - input[type="color" i]::-webkit-color-swatch-wrapper { - padding: 0; - border: 0; - } - - input[type="color" i]::-webkit-color-swatch { - border-radius: 1rem; - padding: 0; - border-color: var(--theme-border); - } - - .editor { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - padding-block: 0.6rem; - } - - .editor:not(:last-of-type) { - border-bottom: 1px solid var(--theme-border); - } - - .editor input { - margin: 0 0.8rem; - } - - #colors { - display: flex; - flex-direction: column; - padding-inline: 2rem; - padding-top: 0.6rem; - } - - #head { - padding: 0.5rem 1rem; - display: flex; - justify-content: space-between; - align-items: center; - position: sticky; - top: 0; - background: var(--theme-bg); - - & > h1 { - margin-left: 0.5rem; - margin-block: 0.9rem; - } - } - - #btns { - display: flex; - gap: 0.15rem; - - & button { - padding: 0.5rem 0.75rem; - border-radius: 10rem; - background: transparent; - color: var(--theme-fg); - border: none; - cursor: pointer; - font-family: inherit; - font-size: 1rem; - - display: flex; - align-items: center; - gap: 0.3rem; - - transition: 0.15s background; - - & .material-symbols-outlined { - font-size: 1.7rem; - } - - &:hover, - &:focus-visible { - background: var(--theme-secondary-bg); - transition: 0.15s background; - outline: none; - } - - &:active { - background: color-mix( - in srgb, - var(--theme-secondary-bg) 90%, - var(--theme-fg) - ); - transition: 0.05s background; - } - } - } - `; - - colorEditors: { - prop: keyof ThemeProps; - name: string; - }[] = [ - { - prop: "background", - name: "Background", - }, - { - prop: "secondaryBackground", - name: "Secondary Background", - }, - { - prop: "darkBackground", - name: "Dark Background", - }, - { - prop: "accent", - name: "Accent", - }, - { - prop: "foreground", - name: "Foreground", - }, - { - prop: "secondaryForeground", - name: "Secondary Foreground", - }, - { - prop: "border", - name: "Border", - }, - { - prop: "darkBorder", - name: "Dark Border", - }, - ]; - - constructor() { - super(); - } - - page = async () => ( -
- - -
- {this.colorEditors.map((color) => ( -
- {color.name} - { - const val = (e.target! as HTMLInputElement) - .value; - anura.ui.theme[color.prop] = val; - anura.settings.set("theme", val, color.prop); - }} - /> -
- ))} -
-
- ); - - async open(args: string[] = []): Promise { - const win = anura.wm.create(this, { - title: "", - width: "910px", - height: `${(720 * window.innerHeight) / 1080}px`, - }); - this.picker = await anura.import("anura.filepicker"); - win.content.appendChild(await this.page()); - - return win; - } - - async importTheme() { - // Here be dragons - const file = await ( - await this.picker - ).selectFile({ regex: "(json|txt)" }); - try { - const data = await anura.fs.promises.readFile(file); - Object.assign(anura.ui.theme.state, JSON.parse(data as any)); - anura.ui.theme.apply(); - await anura.settings.set("theme", anura.ui.theme.state); - } catch (e) { - anura.notifications.add({ - title: "Theme editor", - description: `Theme could not be loaded: ${e}`, - timeout: 5000, - }); - } - } - - exportTheme(theme: string) { - const filePath = `/theme-${Math.floor(Math.random() * 1e10)}.json`; - anura.fs.writeFile(filePath, theme); - anura.notifications.add({ - title: "Theme editor", - description: `Theme saved to ${filePath}`, - timeout: 5000, - }); - } -} diff --git a/src/coreapps/WallpaperSelector.tsx b/src/coreapps/WallpaperSelector.tsx index 9e694a51..909e78b6 100644 --- a/src/coreapps/WallpaperSelector.tsx +++ b/src/coreapps/WallpaperSelector.tsx @@ -1,153 +1,10 @@ -const wallpaperCSS = css` - color: var(--theme-fg); - - .header { - margin-left: 20px; - } - .current-wallpaper { - margin-left: 20px; - display: flex; - align-items: center; - } - .current-wallpaper-image { - aspect-ratio: 16/9; - height: 125px; - border-radius: 10px; - margin-right: 20px; - } - .current-wallpaper-image:hover { - cursor: pointer; - } - .curr-wallpaper-text { - color: var(--theme-secondary-fg); - margin-bottom: 5px; - } - .curr-wallpaper-name { - margin-top: 0px; - } - select { - background-color: var(--theme-secondary-bg); - color: var(--theme-fg); - border: none; - padding: 5px; - border-radius: 5px; - font-family: - "Roboto", - RobotoDraft, - "Droid Sans", - Arial, - Helvetica, - -apple-system, - BlinkMacSystemFont, - system-ui, - sans-serif; - outline: none; - height: 25px; - } - .separator-hr { - margin: 20px; - border: 2px solid var(--theme-border); - border-radius: 10px; - } - *::-webkit-scrollbar { - width: 8px; - } - - *::-webkit-scrollbar-thumb { - background-color: var(--theme-secondary-bg); - border-radius: 8px; - } - - *::-webkit-scrollbar-button { - display: none; - } - .wallpaper-list-container { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - grid-gap: 20px; - margin-left: 20px; - text-align: center; - overflow-y: scroll; - height: calc( - 100% - 264px - ); /* i just realized this was a hacky workaround, can someone make it better - fish */ - } - .wallpaper-list-item { - cursor: pointer; - } - .wallpaper-list-item-image { - aspect-ratio: 16/9; - height: 100px; - - border-radius: 10px; - transition: border 0.2s; - border: 3px solid transparent; /* another shit workaround :frcoal: */ - } - .wallpaper-list-item-name { - margin: 10px; - } - - .wallpaper-list-item.selected img { - border-color: var(--theme-accent); - transition: border 0.2s; - } - - .custom-wallpaper { - margin-left: 20px; - margin-bottom: 20px; - } - - .matter-button-contained { - background-color: var(--theme-accent); - color: var(--theme-fg); - } - - #custom-wallpaper-btn { - display: flex; - justify-content: center; - align-items: center; - background-color: var(--theme-secondary-bg); - color: var(--theme-fg); - border-radius: 10px; - aspect-ratio: 16 / 9; - height: 100px; - width: 177.78px; /* EWW DIRTY HACK PLEASE FIX - fish */ - cursor: pointer; - } - - input[type="color"] { - background-color: transparent; - border: none; - padding: 0; - width: 2.5rem; - height: 25px; - } - - input[type="color" i]::-webkit-color-swatch { - /* This will never work on firefox but who gaf */ - border-radius: 0.5rem; - border: 1px solid var(--theme-border); - height: 25px; - } - - input[type="color" i]::-webkit-color-swatch-wrapper { - padding: 0; - height: 25px; - } - - .wall-fit { - display: flex; - gap: 5px; - } -`; - type WallpaperObject = { name: string; url: string; }; class WallpaperSelector extends App { - name = "Wallpaper Selector"; + name = "Wallpaper & Style"; package = "anura.wallpaper"; icon = "/assets/icons/wallpaper.png"; @@ -162,166 +19,583 @@ class WallpaperSelector extends App { state = $state({ resizing: false, + tab: "wallpapers", }); + css = css` + color: var(--theme-fg); + + .header { + margin-left: 20px; + display: flex; + justify-content: space-between; + } + .current-wallpaper { + margin-left: 20px; + display: flex; + align-items: center; + } + .current-wallpaper-image { + aspect-ratio: 16/9; + height: 125px; + border-radius: 10px; + margin-right: 20px; + } + .current-wallpaper-image:hover { + cursor: pointer; + } + .curr-wallpaper-text { + color: var(--theme-secondary-fg); + margin-bottom: 5px; + } + .curr-wallpaper-name { + margin-top: 0px; + } + select { + background-color: var(--theme-secondary-bg); + color: var(--theme-fg); + border: none; + padding: 5px; + border-radius: 5px; + font-family: + "Roboto", + RobotoDraft, + "Droid Sans", + Arial, + Helvetica, + -apple-system, + BlinkMacSystemFont, + system-ui, + sans-serif; + outline: none; + height: 25px; + } + .separator-hr { + margin: 20px; + border: 2px solid var(--theme-border); + border-radius: 10px; + } + *::-webkit-scrollbar { + width: 8px; + } + + *::-webkit-scrollbar-thumb { + background-color: var(--theme-secondary-bg); + border-radius: 8px; + } + + *::-webkit-scrollbar-button { + display: none; + } + .wallpaper-list-container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-gap: 20px; + margin-left: 20px; + text-align: center; + overflow-y: scroll; + height: calc( + 100% - 264px + ); /* i just realized this was a hacky workaround, can someone make it better - fish */ + } + .wallpaper-list-item { + cursor: pointer; + } + .wallpaper-list-item-image { + aspect-ratio: 16/9; + height: 100px; + + border-radius: 10px; + transition: border 0.2s; + border: 3px solid transparent; /* another shit workaround :frcoal: */ + } + .wallpaper-list-item-name { + margin: 10px; + } + + .wallpaper-list-item.selected img { + border-color: var(--theme-accent); + transition: border 0.2s; + } + + .custom-wallpaper { + margin-left: 20px; + margin-bottom: 20px; + } + + .matter-button-contained { + background-color: var(--theme-accent); + color: var(--theme-fg); + } + + #custom-wallpaper-btn { + display: flex; + justify-content: center; + align-items: center; + background-color: var(--theme-secondary-bg); + color: var(--theme-fg); + border-radius: 10px; + aspect-ratio: 16 / 9; + height: 100px; + width: 177.78px; /* EWW DIRTY HACK PLEASE FIX - fish */ + cursor: pointer; + } + + input[type="color"] { + background-color: transparent; + border: none; + padding: 0; + width: 2.5rem; + height: 25px; + } + + input[type="color" i]::-webkit-color-swatch { + /* This will never work on firefox but who gaf */ + border-radius: 0.5rem; + border: 1px solid var(--theme-border); + height: 25px; + } + + input[type="color" i]::-webkit-color-swatch-wrapper { + padding: 0; + height: 25px; + } + + .wall-fit { + display: flex; + gap: 5px; + } + + width: 100%; + height: 100%; + position: absolute; + overflow-y: auto; + + input[type="color"] { + appearance: none; + background: none; + padding: 0; + border: 0; + border-radius: 1rem; + width: 4rem; + height: 3rem; + } + + input[type="color" i]::-webkit-color-swatch-wrapper { + padding: 0; + border: 0; + } + + input[type="color" i]::-webkit-color-swatch { + border-radius: 1rem; + padding: 0; + border-color: var(--theme-border); + } + + .editor { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + padding-block: 0.6rem; + } + + .editor:not(:last-of-type) { + border-bottom: 1px solid var(--theme-border); + } + + .editor input { + margin: 0 0.8rem; + } + + #colors { + display: flex; + flex-direction: column; + padding-inline: 2rem; + padding-top: 0.6rem; + } + + #head { + padding: 0.5rem 1rem; + display: flex; + justify-content: space-between; + align-items: center; + position: sticky; + top: 0; + background: var(--theme-bg); + + & > h1 { + margin-left: 0.5rem; + margin-block: 0.9rem; + } + } + + #btns { + display: flex; + gap: 0.15rem; + + & button { + padding: 0.5rem 0.75rem; + border-radius: 10rem; + background: transparent; + color: var(--theme-fg); + border: none; + cursor: pointer; + font-family: inherit; + font-size: 1rem; + + display: flex; + align-items: center; + gap: 0.3rem; + + transition: 0.15s background; + + & .material-symbols-outlined { + font-size: 1.7rem; + } + + &:hover, + &:focus-visible { + background: var(--theme-secondary-bg); + transition: 0.15s background; + outline: none; + } + + &:active { + background: color-mix( + in srgb, + var(--theme-secondary-bg) 90%, + var(--theme-fg) + ); + transition: 0.05s background; + } + } + } + + &:has(#colors) h2:not(:first-of-type) { + color: var(--theme-fg); + } + + &:has(#colors) h2 { + color: var(--theme-secondary-fg); + } + + &:not(:has(#colors)) h2 { + color: var(--theme-fg); + } + + &:not(:has(#colors)) h2:not(:first-of-type) { + color: var(--theme-secondary-fg); + } + + h2 { + display: inline-block; + margin-right: 1rem; + } + `; + + colorEditors: { + prop: keyof ThemeProps; + name: string; + }[] = [ + { + prop: "background", + name: "Background", + }, + { + prop: "secondaryBackground", + name: "Secondary Background", + }, + { + prop: "darkBackground", + name: "Dark Background", + }, + { + prop: "accent", + name: "Accent", + }, + { + prop: "foreground", + name: "Foreground", + }, + { + prop: "secondaryForeground", + name: "Secondary Foreground", + }, + { + prop: "border", + name: "Border", + }, + { + prop: "darkBorder", + name: "Dark Border", + }, + ]; + page = async () => (
-

Wallpaper Selector

-
- -
- -
-
- Current Wallpaper -
-

- {this.getCurrentWallpaper().name} -

-
- - {$if( - anura.settings.get("wallpaper-fit") === "contain", - { - anura.settings.set( - "wallpaper-contain-color", - (e.target as HTMLInputElement).value, - ); - window.document.documentElement.style.backgroundColor = - anura.settings.get( - "wallpaper-contain-color", - ); - }} - />, - )} -
-
-
- -
+ + restore + + Reset + + + - {await this.wallpaperList().then((wallpaperJSON: any) => { - const wallpaperList = ( -
-
{ + this.importTheme(); + }} > -
{ - this.libfilepicker - .selectFile({ - regex: "(png|jpe?g|gif|bmp|webp|tiff|svg|ico)", - app: this, - }) - .then((filename: any) => { - if (filename === undefined) return; - const wallpaperName = filename - .split("/") - .pop(); - const wallpaperURL = - "/fs" + filename; - this.setNewWallpaper({ - name: wallpaperName, - url: wallpaperURL, - }); - }); - }} - id="custom-wallpaper-btn" - > - + folder + + Import + + , + )} +
+ {$if( + use(this.state.tab, (tab) => tab === "wallpapers"), +
+
+ +
+
+ Current Wallpaper +
+

+ {this.getCurrentWallpaper().name} +

+
+ + {$if( + anura.settings.get("wallpaper-fit") === + "contain", + { + anura.settings.set( + "wallpaper-contain-color", + (e.target as HTMLInputElement) + .value, + ); + window.document.documentElement.style.backgroundColor = + anura.settings.get( + "wallpaper-contain-color", + ); + }} + />, + )}
-
- Upload new -
- ); - wallpaperJSON["wallpapers"].forEach( - (wallpaper: WallpaperObject) => { - wallpaperList.appendChild( + +
+ + {await this.wallpaperList().then((wallpaperJSON: any) => { + const wallpaperList = (
{ - this.setNewWallpaper(wallpaper); - }} - class={`wallpaper-list-item ${this.getCurrentWallpaper().name === wallpaper.name ? "selected" : ""}`} - id={`wallpaper-${wallpaper.name.replace(" ", "-")}`} + id="wallpaper-list" + class="wallpaper-list-container" > - -
- {wallpaper.name} -
-
, +
{ + this.libfilepicker + .selectFile({ + regex: "(png|jpe?g|gif|bmp|webp|tiff|svg|ico)", + app: this, + }) + .then((filename: any) => { + if (filename === undefined) + return; + const wallpaperName = + filename + .split("/") + .pop(); + const wallpaperURL = + "/fs" + filename; + this.setNewWallpaper({ + name: wallpaperName, + url: wallpaperURL, + }); + }); + }} + id="custom-wallpaper-btn" + > + + add + +
+
+ Upload new +
+
+
+ ); + wallpaperJSON["wallpapers"].forEach( + (wallpaper: WallpaperObject) => { + wallpaperList.appendChild( +
{ + this.setNewWallpaper(wallpaper); + }} + class={`wallpaper-list-item ${this.getCurrentWallpaper().name === wallpaper.name ? "selected" : ""}`} + id={`wallpaper-${wallpaper.name.replace(" ", "-")}`} + > + +
+ {wallpaper.name} +
+
, + ); + }, ); - }, - ); - return wallpaperList; - })} + return wallpaperList; + })} +
, +
+ {this.colorEditors.map((color) => ( +
+ {color.name} + { + const val = (e.target! as HTMLInputElement) + .value; + anura.ui.theme[color.prop] = val; + anura.settings.set( + "theme", + val, + color.prop, + ); + }} + /> +
+ ))} +
, + )}
); @@ -396,6 +670,39 @@ class WallpaperSelector extends App { anura.settings.get("wallpaper-fit"); } + async importTheme() { + // Here be dragons + this.libfilepicker + .selectFile({ regex: "(json|txt)", app: this }) + .then(async (file: any) => { + try { + const data = await anura.fs.promises.readFile(file); + Object.assign( + anura.ui.theme.state, + JSON.parse(data as any), + ); + anura.ui.theme.apply(); + await anura.settings.set("theme", anura.ui.theme.state); + } catch (e) { + anura.notifications.add({ + title: "Theme editor", + description: `Theme could not be loaded: ${e}`, + timeout: 5000, + }); + } + }); + } + + exportTheme(theme: string) { + const filePath = `/theme-${Math.floor(Math.random() * 1e10)}.json`; + anura.fs.writeFile(filePath, theme); + anura.notifications.add({ + title: "Theme editor", + description: `Theme saved to ${filePath}`, + timeout: 5000, + }); + } + constructor() { super(); } From e7f8a39029ac7468424906f7b14e2b778ec83caf Mon Sep 17 00:00:00 2001 From: BomberFish Date: Mon, 2 Dec 2024 18:06:25 -0500 Subject: [PATCH 2/7] Set cursor to pointer in wallpaper & style --- src/coreapps/WallpaperSelector.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreapps/WallpaperSelector.tsx b/src/coreapps/WallpaperSelector.tsx index 909e78b6..6830b821 100644 --- a/src/coreapps/WallpaperSelector.tsx +++ b/src/coreapps/WallpaperSelector.tsx @@ -291,6 +291,7 @@ class WallpaperSelector extends App { h2 { display: inline-block; margin-right: 1rem; + cursor: pointer; } `; From 161db05f5ac6f518f1a8d99a4530e60f2146d351 Mon Sep 17 00:00:00 2001 From: BomberFish Date: Mon, 2 Dec 2024 18:14:26 -0500 Subject: [PATCH 3/7] Remove ThemeEditor.js from index.html --- public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 44b3917a..eadf3716 100755 --- a/public/index.html +++ b/public/index.html @@ -63,10 +63,10 @@ - + > -->