diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreSectionComp.java b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreSectionComp.java index c2db30ce..8ef6dbb7 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreSectionComp.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreSectionComp.java @@ -92,6 +92,7 @@ public class StoreSectionComp extends Comp> { struc.get().getStyleClass().removeIf(s -> Arrays.stream(DataStoreColor.values()) .anyMatch(dataStoreColor -> dataStoreColor.getId().equals(s))); struc.get().getStyleClass().remove("none"); + struc.get().getStyleClass().add("color-box"); if (val != null) { struc.get().getStyleClass().add(val.getId()); } else { diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java b/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java index 2c5c24f5..f9e0075e 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalTerminalType.java @@ -3,10 +3,7 @@ package io.xpipe.app.prefs; import io.xpipe.app.ext.PrefsChoiceValue; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.storage.DataStoreColor; -import io.xpipe.app.util.ApplicationHelper; -import io.xpipe.app.util.MacOsPermissions; -import io.xpipe.app.util.ScriptHelper; -import io.xpipe.app.util.WindowsRegistry; +import io.xpipe.app.util.*; import io.xpipe.core.process.CommandBuilder; import io.xpipe.core.process.OsType; import io.xpipe.core.process.ShellControl; @@ -177,6 +174,27 @@ public interface ExternalTerminalType extends PrefsChoiceValue { } }; +// ExternalTerminalType WEZ_WINDOWS = new WindowsType("app.wezWindows", "wezterm") { +// +// @Override +// protected void execute(Path file, LaunchConfiguration configuration) throws Exception { +// ThreadHelper.runFailableAsync(() -> { +// new LocalStore().control().command(CommandBuilder.of().addFile(file.toString()).add("start", "-e", "cmd", "/c").addFile(configuration.getScriptFile())).execute(); +// }); +// } +// +// @Override +// protected Optional determineInstallation() { +// Optional launcherDir; +// launcherDir = WindowsRegistry.readString( +// WindowsRegistry.HKEY_LOCAL_MACHINE, +// "Microsoft\\Windows\\CurrentVersion\\Uninstall\\{BCF6F0DA-5B9A-408D-8562-F680AE6E1EAF}_is1", +// "InstallLocation") +// .map(p -> p + "\\wezterm.exe"); +// return launcherDir.map(Path::of); +// } +// }; + // ExternalTerminalType HYPER_WINDOWS = new WindowsFullPathType("app.hyperWindows") { // // @Override @@ -478,11 +496,8 @@ public interface ExternalTerminalType extends PrefsChoiceValue { DataStoreColor color; String title; + String cleanTitle; String scriptFile; - - public String getColorPrefix() { - return color != null ? color.getEmoji() + " " : ""; - } } default boolean supportsColoredTitle() { diff --git a/app/src/main/java/io/xpipe/app/storage/StandardStorage.java b/app/src/main/java/io/xpipe/app/storage/StandardStorage.java index 56cb2e49..1a5af586 100644 --- a/app/src/main/java/io/xpipe/app/storage/StandardStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/StandardStorage.java @@ -257,10 +257,14 @@ public class StandardStorage extends DataStorage { e.setDirectory(getStoresDir().resolve(LOCAL_ID.toString())); e.setConfiguration( StorageElement.Configuration.builder().deletable(false).build()); - e.setColor(DataStoreColor.BLUE); storeEntries.add(e); e.validate(); } + + var local = DataStorage.get().getStoreEntry(LOCAL_ID); + if (storeEntries.stream().noneMatch(entry -> entry.getColor() != null)) { + local.setColor(DataStoreColor.BLUE); + } } // Refresh to update state diff --git a/app/src/main/java/io/xpipe/app/util/TerminalHelper.java b/app/src/main/java/io/xpipe/app/util/TerminalHelper.java index bb18174b..bd2e2b31 100644 --- a/app/src/main/java/io/xpipe/app/util/TerminalHelper.java +++ b/app/src/main/java/io/xpipe/app/util/TerminalHelper.java @@ -27,9 +27,10 @@ public class TerminalHelper { var prefix = entry != null && color != null && type.supportsColoredTitle() ? color.getEmoji() + " " : ""; - var fixedTitle = prefix + (title != null ? title : entry != null ? entry.getName() : "?"); - var file = ScriptHelper.createLocalExecScript(cc.prepareTerminalOpen(fixedTitle)); - var config = new ExternalTerminalType.LaunchConfiguration(entry != null ? color : null, title, file); + var cleanTitle = (title != null ? title : entry != null ? entry.getName() : "?"); + var adjustedTitle = prefix + cleanTitle; + var file = ScriptHelper.createLocalExecScript(cc.prepareTerminalOpen(adjustedTitle)); + var config = new ExternalTerminalType.LaunchConfiguration(entry != null ? color : null, adjustedTitle, cleanTitle, file); try { type.launch(config); } catch (Exception ex) { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/color-box.css b/app/src/main/resources/io/xpipe/app/resources/style/color-box.css index f73012d9..3b22b945 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/color-box.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/color-box.css @@ -1,3 +1,17 @@ +.root:dark .color-box { + -fx-background-color: linear-gradient(from 100% 0% to 0% 100%, derive(-color-bg-default, 5%) 40%, derive(-color-bg-default, 1%) 50%, derive(-color-bg-default, 5%) 100%); + -fx-border-color: -color-border-default; +} + +.root:light .color-box { + -fx-background-color: linear-gradient(from 100% 0% to 0% 100%, derive(-color-bg-default, -8%) 40%, derive(-color-bg-default, -3%) 50%, derive(-color-bg-default, -8%) 100%); + -fx-border-color: derive(-color-border-default, -10%); +} + +.color-box > .separator .line { + -fx-border-color: -color-border-default; +} + .root:light .color-box.blue { -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(130, 130, 250, 0.2) 40%, rgb(57, 57, 200, 0.2) 50%, rgb(137, 137, 250, 0.2) 100%); -fx-border-color: rgba(80, 100, 150, 0.3); diff --git a/app/src/main/resources/io/xpipe/app/resources/style/license-required-alert.css b/app/src/main/resources/io/xpipe/app/resources/style/license-required-alert.css deleted file mode 100644 index cab94511..00000000 --- a/app/src/main/resources/io/xpipe/app/resources/style/license-required-alert.css +++ /dev/null @@ -1,11 +0,0 @@ -.license-required { - -fx-padding: 1em; - -fx-font-family: Roboto; -} - -.license-required .message { --fx-border-width: 1px; --fx-border-radius: 15px; --fx-background-radius: 15px; --fx-padding: 1em; -} diff --git a/app/src/main/resources/io/xpipe/app/resources/style/multi-step-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/multi-step-comp.css index 118de202..7be41211 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/multi-step-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/multi-step-comp.css @@ -3,7 +3,7 @@ -fx-background-color: -color-accent-fg; } -.multi-step-comp .entry { +.multi-step-comp > .entry { -fx-spacing: 0.2em; -fx-padding: 0.6em 0 1em 0; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css index fa9fb36d..364006cb 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css @@ -135,80 +135,6 @@ -fx-border-color: -color-border-default; } -/* Colors */ - -.root:light .top > .store-entry-section-comp.blue { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(130, 130, 250, 0.2) 40%, rgb(57, 57, 200, 0.2) 50%, rgb(137, 137, 250, 0.2) 100%); - -fx-border-color: rgba(80, 100, 150, 0.3); -} - -.root:light .top > .store-entry-section-comp.blue > .separator .line { - -fx-border-color: rgba(80, 100, 150, 0.4); -} - -.root:dark .top > .store-entry-section-comp.blue { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(30, 30, 80, 0.8) 40%, rgb(27, 27, 65, 0.8) 50%, rgb(37, 37, 100, 0.8) 100%); - -fx-border-color: rgba(80, 100, 150, 0.7); -} - -.root:dark .top > .store-entry-section-comp.blue > .separator .line { - -fx-border-color: rgba(80, 100, 150, 0.7); -} - -.root:light .top > .store-entry-section-comp.red { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(220, 100, 100, 0.15) 40%, rgb(205, 50, 50, 0.15) 50%, rgb(200, 90, 90, 0.15) 100%); - -fx-border-color: rgba(150, 100, 80, 0.4); -} - -.root:light .top > .store-entry-section-comp.red > .separator .line { - -fx-border-color: rgba(150, 100, 80, 0.4); -} - -.root:dark .top > .store-entry-section-comp.red { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(80, 30, 30, 0.4) 40%, rgb(65, 27, 27, 0.4) 50%, rgb(100, 37, 37, 0.4) 100%); - -fx-border-color: rgba(150, 100, 80, 0.4); -} - -.root:dark .top > .store-entry-section-comp.red > .separator .line { - -fx-border-color: rgba(150, 100, 80, 0.4); -} - -.root:light .top > .store-entry-section-comp.yellow { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(180, 180, 30, 0.2) 40%, rgb(135, 135, 27, 0.2) 50%, rgb(200, 200, 37, 0.2) 100%); - -fx-border-color: rgba(170, 170, 80, 0.3); -} - -.root:light .top > .store-entry-section-comp.yellow > .separator .line { - -fx-border-color: rgba(170, 170, 80, 0.5); -} - -.root:dark .top > .store-entry-section-comp.yellow { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(80, 80, 30, 0.4) 40%, rgb(65, 65, 27, 0.4) 50%, rgb(100, 100, 37, 0.4) 100%); - -fx-border-color: rgba(150, 150, 80, 0.4); -} - -.root:dark .top > .store-entry-section-comp.yellow > .separator .line { - -fx-border-color: rgba(170, 170, 80, 0.3); -} - -.root:light .top > .store-entry-section-comp.green { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(30, 180, 30, 0.1) 40%, rgb(20, 120, 20, 0.15) 50%, rgb(37, 200, 37, 0.1) 100%); - -fx-border-color: rgba(100, 150, 80, 0.2); -} - -.root:light .top > .store-entry-section-comp.green > .separator .line { - -fx-border-color: rgba(100, 150, 80, 0.4); -} - -.root:dark .top > .store-entry-section-comp.green { - -fx-background-color: linear-gradient(from 100% 0% to 0% 100% , rgb(30, 80, 30, 0.3) 40%, rgb(20, 60, 20, 0.3) 50%, rgb(37, 100, 37, 0.3) 100%); - -fx-border-color: rgba(100, 190, 80, 0.3); -} - -.root:dark .top > .store-entry-section-comp.green > .separator .line { - -fx-border-color: rgba(100, 190, 80, 0.2); -} - /* Light sub backgrounds */ .root:light .store-entry-section-comp:sub:expanded { diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStore.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStore.java index 7d739f6f..3f08e0af 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStore.java @@ -9,8 +9,8 @@ import lombok.Getter; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; @Getter @SuperBuilder @@ -24,10 +24,10 @@ public class ScriptGroupStore extends ScriptStore implements GroupStore getFlattenedScripts(Set seen) { - return getEffectiveScripts().stream().map(scriptStoreDataStoreEntryRef -> { - return scriptStoreDataStoreEntryRef.getStore().getFlattenedScripts(seen); - }).flatMap(List::stream).toList(); + protected void queryFlattenedScripts(LinkedHashSet all) { + getEffectiveScripts().forEach(simpleScriptStore -> { + simpleScriptStore.getStore().queryFlattenedScripts(all); + }); } @Override diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStoreProvider.java index bd7297df..a7cebba7 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptGroupStoreProvider.java @@ -1,5 +1,7 @@ package io.xpipe.ext.base.script; +import io.xpipe.app.comp.base.DropdownComp; +import io.xpipe.app.comp.base.StoreToggleComp; import io.xpipe.app.comp.base.SystemStateComp; import io.xpipe.app.comp.storage.store.DenseStoreEntryComp; import io.xpipe.app.comp.storage.store.StoreEntryWrapper; @@ -22,6 +24,18 @@ import java.util.List; public class ScriptGroupStoreProvider implements DataStoreProvider { + @Override + public Comp customEntryComp(StoreSection sec, boolean preferLarge) { + ScriptGroupStore s = sec.getWrapper().getEntry().getStore().asNeeded(); + var def = new StoreToggleComp("base.isDefaultGroup", sec, s.getState().isDefault(), aBoolean -> { + var state = s.getState(); + state.setDefault(aBoolean); + s.setState(state); + }); + var dropdown = new DropdownComp(List.of(def)); + return new DenseStoreEntryComp(sec.getWrapper(), true, dropdown); + } + @SneakyThrows @Override public GuiDialog guiDialog(DataStoreEntry entry, Property store) { @@ -61,11 +75,6 @@ public class ScriptGroupStoreProvider implements DataStoreProvider { return new SystemStateComp(new SimpleObjectProperty<>(SystemStateComp.State.SUCCESS)); } - @Override - public Comp customEntryComp(StoreSection s, boolean preferLarge) { - return new DenseStoreEntryComp(s.getWrapper(), true, null); - } - @Override public CreationCategory getCreationCategory() { return CreationCategory.SCRIPT; diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java index a4b624cf..91d02117 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java @@ -13,10 +13,7 @@ import lombok.experimental.FieldDefaults; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @SuperBuilder @@ -58,12 +55,11 @@ public abstract class ScriptStore extends JacksonizedValue implements DataStore, } public static List flatten(List> scripts) { - var seen = new HashSet(); - return scripts.stream() - .map(scriptStoreDataStoreEntryRef -> - scriptStoreDataStoreEntryRef.getStore().getFlattenedScripts(seen)) - .flatMap(List::stream) - .toList(); + var seen = new LinkedHashSet(); + scripts + .forEach(scriptStoreDataStoreEntryRef -> + scriptStoreDataStoreEntryRef.getStore().queryFlattenedScripts(seen)); + return seen.stream().toList(); } protected final DataStoreEntryRef group; @@ -95,11 +91,13 @@ public abstract class ScriptStore extends JacksonizedValue implements DataStore, } } - public List getFlattenedScripts() { - return getFlattenedScripts(new HashSet<>()); + public LinkedHashSet getFlattenedScripts() { + var set = new LinkedHashSet(); + queryFlattenedScripts(set); + return set; } - protected abstract List getFlattenedScripts(Set seen); + protected abstract void queryFlattenedScripts(LinkedHashSet all); public abstract List> getEffectiveScripts(); } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java index a4c0669d..27f550f7 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStore.java @@ -11,9 +11,8 @@ import lombok.Getter; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; -import java.util.stream.Stream; @SuperBuilder @Getter @@ -47,21 +46,11 @@ public class SimpleScriptStore extends ScriptStore { : List.of(); } - @Override - public List getFlattenedScripts(Set seen) { - var isLoop = seen.contains(this); - seen.add(this); - return Stream.concat( - getEffectiveScripts().stream() - .map(scriptStoreDataStoreEntryRef -> { - return scriptStoreDataStoreEntryRef.getStore().getFlattenedScripts(seen).stream() - .filter(simpleScriptStore -> !seen.contains(simpleScriptStore)) - .peek(simpleScriptStore -> seen.add(simpleScriptStore)) - .toList(); - }) - .flatMap(List::stream), - isLoop ? Stream.of() : Stream.of(this)) - .toList(); + public void queryFlattenedScripts(LinkedHashSet all) { + getEffectiveScripts().stream().filter(scriptStoreDataStoreEntryRef -> !all.contains(scriptStoreDataStoreEntryRef.getStore())).forEach(scriptStoreDataStoreEntryRef -> { + scriptStoreDataStoreEntryRef.getStore().queryFlattenedScripts(all); + }); + all.add(this); } @Getter diff --git a/ext/base/src/main/resources/io/xpipe/ext/base/resources/lang/translations_en.properties b/ext/base/src/main/resources/io/xpipe/ext/base/resources/lang/translations_en.properties index 84769e15..256732a6 100644 --- a/ext/base/src/main/resources/io/xpipe/ext/base/resources/lang/translations_en.properties +++ b/ext/base/src/main/resources/io/xpipe/ext/base/resources/lang/translations_en.properties @@ -73,6 +73,7 @@ snippets=Script dependencies snippetsDescription=Other scripts to run first snippetsDependenciesDescription=All possible scripts that should be run if applicable isDefault=Enable in all compatible shells +isDefaultGroup=Enable all group scripts executionType=Execution type executionTypeDescription=When to run this snippet minimumShellDialect=Shell type