mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
About page polish [stage]
This commit is contained in:
parent
1aa50d50ca
commit
67eee13fca
6 changed files with 151 additions and 121 deletions
|
@ -3,7 +3,8 @@ package io.xpipe.app.comp.base;
|
||||||
import atlantafx.base.theme.Styles;
|
import atlantafx.base.theme.Styles;
|
||||||
import io.xpipe.app.core.AppFont;
|
import io.xpipe.app.core.AppFont;
|
||||||
import io.xpipe.app.core.AppI18n;
|
import io.xpipe.app.core.AppI18n;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
|
import io.xpipe.app.fxcomps.CompStructure;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
|
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
|
@ -13,43 +14,28 @@ import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Value;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
public class TileButtonComp extends SimpleComp {
|
public class TileButtonComp extends Comp<TileButtonComp.Structure> {
|
||||||
|
|
||||||
private final ObservableValue<String> name;
|
|
||||||
private final ObservableValue<String> description;
|
|
||||||
private final ObservableValue<String> icon;
|
|
||||||
private final Consumer<ActionEvent> action;
|
|
||||||
|
|
||||||
public TileButtonComp(String nameKey, String descriptionKey, String icon, Consumer<ActionEvent> action) {
|
|
||||||
this.name = AppI18n.observable(nameKey);
|
|
||||||
this.description = AppI18n.observable(descriptionKey);
|
|
||||||
this.icon = new SimpleStringProperty(icon);
|
|
||||||
this.action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Region createSimple() {
|
public Structure createBase() {
|
||||||
var bt = new Button();
|
var bt = new Button();
|
||||||
bt.setGraphic(createNamedEntry());
|
|
||||||
Styles.toggleStyleClass(bt, Styles.FLAT);
|
Styles.toggleStyleClass(bt, Styles.FLAT);
|
||||||
bt.setOnAction(e -> {
|
bt.setOnAction(e -> {
|
||||||
action.accept(e);
|
action.accept(e);
|
||||||
});
|
});
|
||||||
return bt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Region createNamedEntry() {
|
|
||||||
var header = new Label();
|
var header = new Label();
|
||||||
header.textProperty().bind(PlatformThread.sync(name));
|
header.textProperty().bind(PlatformThread.sync(name));
|
||||||
var desc = new Label();
|
var desc = new Label();
|
||||||
|
@ -81,6 +67,34 @@ public class TileButtonComp extends SimpleComp {
|
||||||
var size = Math.min(n.intValue(), 100);
|
var size = Math.min(n.intValue(), 100);
|
||||||
fi.setIconSize((int) (size * 0.55));
|
fi.setIconSize((int) (size * 0.55));
|
||||||
});
|
});
|
||||||
return hbox;
|
bt.setGraphic(hbox);
|
||||||
|
return Structure.builder().graphic(fi).button(bt).content(hbox).name(header).description(desc).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@Builder
|
||||||
|
public static class Structure implements CompStructure<Button> {
|
||||||
|
Button button;
|
||||||
|
HBox content;
|
||||||
|
FontIcon graphic;
|
||||||
|
Label name;
|
||||||
|
Label description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Button get() {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ObservableValue<String> name;
|
||||||
|
private final ObservableValue<String> description;
|
||||||
|
private final ObservableValue<String> icon;
|
||||||
|
private final Consumer<ActionEvent> action;
|
||||||
|
|
||||||
|
public TileButtonComp(String nameKey, String descriptionKey, String icon, Consumer<ActionEvent> action) {
|
||||||
|
this.name = AppI18n.observable(nameKey);
|
||||||
|
this.description = AppI18n.observable(descriptionKey);
|
||||||
|
this.icon = new SimpleStringProperty(icon);
|
||||||
|
this.action = action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.xpipe.app.fxcomps.util.SimpleChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.ButtonBase;
|
import javafx.scene.control.ButtonBase;
|
||||||
|
import javafx.scene.control.Separator;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.input.KeyCombination;
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
@ -32,6 +33,10 @@ public abstract class Comp<S extends CompStructure<?>> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Comp<CompStructure<Separator>> separator() {
|
||||||
|
return Comp.of(() -> new Separator());
|
||||||
|
}
|
||||||
|
|
||||||
public static <S extends CompStructure<?>> Comp<S> ofStructure(Supplier<S> r) {
|
public static <S extends CompStructure<?>> Comp<S> ofStructure(Supplier<S> r) {
|
||||||
return new WrapperComp<>(r);
|
return new WrapperComp<>(r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,8 @@ import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.store.ShellStore;
|
import io.xpipe.core.store.ShellStore;
|
||||||
import io.xpipe.core.util.XPipeInstallation;
|
import io.xpipe.core.util.XPipeInstallation;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -32,7 +30,6 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
|
|
||||||
private Comp<?> createActions() {
|
private Comp<?> createActions() {
|
||||||
return new OptionsBuilder()
|
return new OptionsBuilder()
|
||||||
.addTitle("usefulActions")
|
|
||||||
.addComp(
|
.addComp(
|
||||||
new TileButtonComp("reportIssue", "reportIssueDescription", "mdal-bug_report", e -> {
|
new TileButtonComp("reportIssue", "reportIssueDescription", "mdal-bug_report", e -> {
|
||||||
var event = ErrorEvent.fromMessage("User Report");
|
var event = ErrorEvent.fromMessage("User Report");
|
||||||
|
@ -44,6 +41,31 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
})
|
})
|
||||||
.grow(true, false),
|
.grow(true, false),
|
||||||
null)
|
null)
|
||||||
|
.addComp(
|
||||||
|
new TileButtonComp(
|
||||||
|
"launchDebugMode", "launchDebugModeDescription", "mdmz-refresh", e -> {
|
||||||
|
OperationMode.executeAfterShutdown(() -> {
|
||||||
|
try (var sc = ShellStore.createLocal()
|
||||||
|
.control()
|
||||||
|
.start()) {
|
||||||
|
var script = FileNames.join(
|
||||||
|
XPipeInstallation.getCurrentInstallationBasePath()
|
||||||
|
.toString(),
|
||||||
|
XPipeInstallation.getDaemonDebugScriptPath(sc.getOsType()));
|
||||||
|
if (sc.getOsType().equals(OsType.WINDOWS)) {
|
||||||
|
sc.executeSimpleCommand(ScriptHelper.createDetachCommand(
|
||||||
|
sc, "\"" + script + "\""));
|
||||||
|
} else {
|
||||||
|
TerminalHelper.open("XPipe Debug", "\"" + script + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DesktopHelper.browsePath(
|
||||||
|
AppLogs.get().getSessionLogsDirectory());
|
||||||
|
e.consume();
|
||||||
|
})
|
||||||
|
.grow(true, false),
|
||||||
|
null)
|
||||||
.addComp(
|
.addComp(
|
||||||
new TileButtonComp(
|
new TileButtonComp(
|
||||||
"openCurrentLogFile",
|
"openCurrentLogFile",
|
||||||
|
@ -58,31 +80,6 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
})
|
})
|
||||||
.grow(true, false),
|
.grow(true, false),
|
||||||
null)
|
null)
|
||||||
.addComp(
|
|
||||||
new TileButtonComp(
|
|
||||||
"launchDebugMode", "launchDebugModeDescription", "mdmz-refresh", e -> {
|
|
||||||
OperationMode.executeAfterShutdown(() -> {
|
|
||||||
try (var sc = ShellStore.createLocal()
|
|
||||||
.control()
|
|
||||||
.start()) {
|
|
||||||
var script = FileNames.join(
|
|
||||||
XPipeInstallation.getCurrentInstallationBasePath()
|
|
||||||
.toString(),
|
|
||||||
XPipeInstallation.getDaemonDebugScriptPath(sc.getOsType()));
|
|
||||||
if (sc.getOsType().equals(OsType.WINDOWS)) {
|
|
||||||
sc.executeSimpleCommand(ScriptHelper.createDetachCommand(
|
|
||||||
sc, "\"" + script + "\""));
|
|
||||||
} else {
|
|
||||||
TerminalHelper.open("XPipe Debug", "\"" + script + "\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
DesktopHelper.browsePath(
|
|
||||||
AppLogs.get().getSessionLogsDirectory());
|
|
||||||
e.consume();
|
|
||||||
})
|
|
||||||
.grow(true, false),
|
|
||||||
null)
|
|
||||||
.addComp(
|
.addComp(
|
||||||
new TileButtonComp(
|
new TileButtonComp(
|
||||||
"openInstallationDirectory",
|
"openInstallationDirectory",
|
||||||
|
@ -100,34 +97,6 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
|
|
||||||
private Comp<?> createLinks() {
|
private Comp<?> createLinks() {
|
||||||
return new OptionsBuilder()
|
return new OptionsBuilder()
|
||||||
.addComp(
|
|
||||||
new TileButtonComp(
|
|
||||||
"securityPolicy", "securityPolicyDescription", "mdrmz-security", e -> {
|
|
||||||
Hyperlinks.open(Hyperlinks.SECURITY);
|
|
||||||
e.consume();
|
|
||||||
})
|
|
||||||
.grow(true, false),
|
|
||||||
null)
|
|
||||||
.addComp(
|
|
||||||
new TileButtonComp("privacy", "privacyDescription", "mdomz-privacy_tip", e -> {
|
|
||||||
Hyperlinks.open(Hyperlinks.PRIVACY);
|
|
||||||
e.consume();
|
|
||||||
})
|
|
||||||
.grow(true, false),
|
|
||||||
null)
|
|
||||||
.addComp(
|
|
||||||
new TileButtonComp(
|
|
||||||
"thirdParty", "thirdPartyDescription", "mdi2o-open-source-initiative", e -> {
|
|
||||||
AppWindowHelper.sideWindow(
|
|
||||||
AppI18n.get("openSourceNotices"),
|
|
||||||
stage -> Comp.of(() -> createThirdPartyDeps()),
|
|
||||||
true,
|
|
||||||
null)
|
|
||||||
.show();
|
|
||||||
e.consume();
|
|
||||||
})
|
|
||||||
.grow(true, false),
|
|
||||||
null)
|
|
||||||
.addComp(
|
.addComp(
|
||||||
new TileButtonComp("discord", "discordDescription", "mdi2d-discord", e -> {
|
new TileButtonComp("discord", "discordDescription", "mdi2d-discord", e -> {
|
||||||
Hyperlinks.open(Hyperlinks.DISCORD);
|
Hyperlinks.open(Hyperlinks.DISCORD);
|
||||||
|
@ -149,6 +118,34 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
})
|
})
|
||||||
.grow(true, false),
|
.grow(true, false),
|
||||||
null)
|
null)
|
||||||
|
.addComp(
|
||||||
|
new TileButtonComp(
|
||||||
|
"securityPolicy", "securityPolicyDescription", "mdrmz-security", e -> {
|
||||||
|
Hyperlinks.open(Hyperlinks.SECURITY);
|
||||||
|
e.consume();
|
||||||
|
})
|
||||||
|
.grow(true, false),
|
||||||
|
null)
|
||||||
|
.addComp(
|
||||||
|
new TileButtonComp("privacy", "privacyDescription", "mdomz-privacy_tip", e -> {
|
||||||
|
Hyperlinks.open(Hyperlinks.PRIVACY);
|
||||||
|
e.consume();
|
||||||
|
})
|
||||||
|
.grow(true, false),
|
||||||
|
null)
|
||||||
|
.addComp(
|
||||||
|
new TileButtonComp(
|
||||||
|
"thirdParty", "thirdPartyDescription", "mdi2o-open-source-initiative", e -> {
|
||||||
|
AppWindowHelper.sideWindow(
|
||||||
|
AppI18n.get("openSourceNotices"),
|
||||||
|
stage -> Comp.of(() -> createThirdPartyDeps()),
|
||||||
|
true,
|
||||||
|
null)
|
||||||
|
.show();
|
||||||
|
e.consume();
|
||||||
|
})
|
||||||
|
.grow(true, false),
|
||||||
|
null)
|
||||||
.buildComp();
|
.buildComp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,19 +162,13 @@ public class AboutComp extends Comp<CompStructure<?>> {
|
||||||
@Override
|
@Override
|
||||||
public CompStructure<?> createBase() {
|
public CompStructure<?> createBase() {
|
||||||
var props = new PropertiesComp().padding(new Insets(0, 0, 0, 15));
|
var props = new PropertiesComp().padding(new Insets(0, 0, 0, 15));
|
||||||
var update = Comp.derive(new UpdateCheckComp(), u -> {
|
var update = new UpdateCheckComp().grow(true, false);
|
||||||
var sp = new StackPane(u);
|
var box = new VerticalComp(List.of(props, Comp.separator(), update, Comp.separator(), createLinks(), Comp.separator(), createActions()))
|
||||||
sp.setAlignment(Pos.CENTER);
|
|
||||||
sp.setPadding(new Insets(10, 0, 10, 15));
|
|
||||||
return sp;
|
|
||||||
})
|
|
||||||
.grow(true, false);
|
|
||||||
var box = new VerticalComp(List.of(props, update, createLinks(), createActions()))
|
|
||||||
.apply(s -> s.get().setFillWidth(true))
|
.apply(s -> s.get().setFillWidth(true))
|
||||||
.apply(struc -> struc.get().setSpacing(15))
|
.apply(struc -> struc.get().setSpacing(15))
|
||||||
.styleClass("information")
|
.styleClass("information")
|
||||||
.styleClass("about-tab")
|
.styleClass("about-tab")
|
||||||
.apply(struc -> struc.get().setPrefWidth(800));
|
.apply(struc -> struc.get().setPrefWidth(600));
|
||||||
return box.createStructure();
|
return box.createStructure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.app.prefs;
|
package io.xpipe.app.prefs;
|
||||||
|
|
||||||
|
import atlantafx.base.controls.Spacer;
|
||||||
|
import io.xpipe.app.comp.base.TileButtonComp;
|
||||||
import io.xpipe.app.core.AppI18n;
|
import io.xpipe.app.core.AppI18n;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
|
@ -10,11 +12,9 @@ import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
|
||||||
|
|
||||||
public class UpdateCheckComp extends SimpleComp {
|
public class UpdateCheckComp extends SimpleComp {
|
||||||
|
|
||||||
|
@ -52,7 +52,11 @@ public class UpdateCheckComp extends SimpleComp {
|
||||||
.getPreparedUpdate()
|
.getPreparedUpdate()
|
||||||
.getValue()
|
.getValue()
|
||||||
!= null) {
|
!= null) {
|
||||||
return null;
|
return "Version " + XPipeDistributionType.get()
|
||||||
|
.getUpdateHandler()
|
||||||
|
.getPreparedUpdate()
|
||||||
|
.getValue()
|
||||||
|
.getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XPipeDistributionType.get()
|
if (XPipeDistributionType.get()
|
||||||
|
@ -98,44 +102,51 @@ public class UpdateCheckComp extends SimpleComp {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Region createSimple() {
|
protected Region createSimple() {
|
||||||
var button = new Button();
|
var name = Bindings.createStringBinding(
|
||||||
button.disableProperty()
|
() -> {
|
||||||
.bind(PlatformThread.sync(
|
if (updateReady.getValue()) {
|
||||||
XPipeDistributionType.get().getUpdateHandler().getBusy()));
|
return AppI18n.get("updateReady");
|
||||||
button.textProperty()
|
}
|
||||||
.bind(Bindings.createStringBinding(
|
|
||||||
() -> {
|
|
||||||
if (updateReady.getValue()) {
|
|
||||||
return AppI18n.get("updateReady");
|
|
||||||
}
|
|
||||||
|
|
||||||
return AppI18n.get("checkForUpdates");
|
return AppI18n.get("checkForUpdates");
|
||||||
},
|
},
|
||||||
updateReady));
|
updateReady);
|
||||||
button.graphicProperty()
|
var description = Bindings.createStringBinding(
|
||||||
.bind(Bindings.createObjectBinding(
|
() -> {
|
||||||
() -> {
|
if (updateReady.getValue()) {
|
||||||
if (updateReady.getValue()) {
|
return AppI18n.get("updateReadyDescription");
|
||||||
return new FontIcon("mdi2a-apple-airplay");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return new FontIcon("mdi2r-refresh");
|
return AppI18n.get("checkForUpdatesDescription");
|
||||||
},
|
},
|
||||||
updateReady));
|
updateReady);
|
||||||
button.getStyleClass().add("button-comp");
|
var graphic = Bindings.createObjectBinding(
|
||||||
button.setOnAction(e -> {
|
() -> {
|
||||||
if (updateReady.getValue()) {
|
if (updateReady.getValue()) {
|
||||||
restart();
|
return "mdi2a-apple-airplay";
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
refresh();
|
return "mdi2r-refresh";
|
||||||
});
|
},
|
||||||
|
updateReady);
|
||||||
|
var button = new TileButtonComp(name, description, graphic, actionEvent -> {
|
||||||
|
actionEvent.consume();
|
||||||
|
if (updateReady.getValue()) {
|
||||||
|
restart();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
})
|
||||||
|
.styleClass("button-comp")
|
||||||
|
.disable(PlatformThread.sync(
|
||||||
|
XPipeDistributionType.get().getUpdateHandler().getBusy()))
|
||||||
|
.createRegion();
|
||||||
|
|
||||||
var checked = new Label();
|
var checked = new Label();
|
||||||
checked.textProperty().bind(descriptionText());
|
checked.textProperty().bind(descriptionText());
|
||||||
|
|
||||||
var box = new HBox(button, checked);
|
var box = new HBox(button, new Spacer(), checked, new Spacer(15));
|
||||||
box.setAlignment(Pos.CENTER_LEFT);
|
box.setAlignment(Pos.CENTER_LEFT);
|
||||||
box.setFillHeight(true);
|
box.setFillHeight(true);
|
||||||
box.getStyleClass().add("update-check");
|
box.getStyleClass().add("update-check");
|
||||||
|
|
|
@ -181,12 +181,14 @@ githubDescription=Check out the GitHub repository
|
||||||
openSourceNotices=Open Source Notices
|
openSourceNotices=Open Source Notices
|
||||||
xPipeClient=XPipe Desktop
|
xPipeClient=XPipe Desktop
|
||||||
checkForUpdates=Check for updates
|
checkForUpdates=Check for updates
|
||||||
|
checkForUpdatesDescription=Download an update if there is one
|
||||||
lastChecked=Last checked
|
lastChecked=Last checked
|
||||||
version=Version
|
version=Version
|
||||||
build=Build
|
build=Build
|
||||||
runtimeVersion=Runtime version
|
runtimeVersion=Runtime version
|
||||||
virtualMachine=Virtual machine
|
virtualMachine=Virtual machine
|
||||||
updateReady=Update ready
|
updateReady=Install update
|
||||||
|
updateReadyDescription=An update was downloaded and is ready to be installed
|
||||||
updateRestart=Restart to update
|
updateRestart=Restart to update
|
||||||
never=Never
|
never=Never
|
||||||
updateAvailable=Update available: $VERSION$
|
updateAvailable=Update available: $VERSION$
|
||||||
|
|
|
@ -14,6 +14,13 @@ newLink=New link
|
||||||
linkName=Link name
|
linkName=Link name
|
||||||
targetPath=Target path
|
targetPath=Target path
|
||||||
newDirectory=New directory
|
newDirectory=New directory
|
||||||
|
terminator=Terminator
|
||||||
|
kitty=Kitty
|
||||||
|
terminology=Terminology
|
||||||
|
coolRetroTerm=Cool Retro Term
|
||||||
|
guake=Guake
|
||||||
|
alacritty=Alacritty
|
||||||
|
tilda=Tilda
|
||||||
copyShareLink=Copy share link
|
copyShareLink=Copy share link
|
||||||
selectStore=Select Store
|
selectStore=Select Store
|
||||||
saveSource=Save for later
|
saveSource=Save for later
|
||||||
|
|
Loading…
Reference in a new issue