diff --git a/app/gradle_scripts/sentry.gradle b/app/gradle_scripts/sentry.gradle index 8ccf04cb..12b74596 100644 --- a/app/gradle_scripts/sentry.gradle +++ b/app/gradle_scripts/sentry.gradle @@ -1,5 +1,5 @@ dependencies { - implementation files("$buildDir/generated-modules/sentry-6.11.0.jar") + implementation files("$buildDir/generated-modules/sentry-6.16.0.jar") } addDependenciesModuleInfo { @@ -8,7 +8,7 @@ addDependenciesModuleInfo { outputDirectory = file("$buildDir/generated-modules") modules { module { - artifact 'io.sentry:sentry:6.11.0' + artifact 'io.sentry:sentry:6.16.0' moduleInfoSource = ''' module io.sentry { exports io.sentry; diff --git a/app/src/main/java/io/xpipe/app/browser/FileListComp.java b/app/src/main/java/io/xpipe/app/browser/FileListComp.java index b2e894b3..4d13d3b9 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/FileListComp.java @@ -210,6 +210,17 @@ final class FileListComp extends AnchorPane { newItems.add(parentEntry); } newItems.addAll(newValue); + + var hasModifiedDate = + newItems.size() == 0 || newItems.stream().anyMatch(entry -> entry.getDate() != null); + if (!hasModifiedDate) { + table.getColumns().remove(mtimeCol); + } else { + if (!table.getColumns().contains(mtimeCol)) { + table.getColumns().add(mtimeCol); + } + } + table.getItems().setAll(newItems); var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory(); diff --git a/app/src/main/java/io/xpipe/app/comp/about/AboutTabComp.java b/app/src/main/java/io/xpipe/app/comp/about/AboutTabComp.java index 66c6c2fe..6f03b6ea 100644 --- a/app/src/main/java/io/xpipe/app/comp/about/AboutTabComp.java +++ b/app/src/main/java/io/xpipe/app/comp/about/AboutTabComp.java @@ -36,7 +36,6 @@ public class AboutTabComp extends Comp> { private Comp createLinks() { return new DynamicOptionsBuilder(false) .addTitle("links") - .addComp(AppI18n.observable("website"), hyperlink(Hyperlinks.WEBSITE), null) .addComp(AppI18n.observable("documentation"), hyperlink(Hyperlinks.DOCUMENTATION), null) .addComp(AppI18n.observable("discord"), hyperlink(Hyperlinks.DISCORD), null) .addComp(AppI18n.observable("slack"), hyperlink(Hyperlinks.SLACK), null) diff --git a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java index 7dae310b..f23dcdde 100644 --- a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java +++ b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java @@ -28,7 +28,7 @@ public class AppExtensionManager { private ModuleLayer baseLayer = ModuleLayer.boot(); private ModuleLayer extendedLayer; - public static void init(boolean loadProviders) { + public static void init(boolean loadProviders) throws Exception { if (INSTANCE != null) { return; } diff --git a/app/src/main/java/io/xpipe/app/core/AppProperties.java b/app/src/main/java/io/xpipe/app/core/AppProperties.java index ebf907f0..2030e4e0 100644 --- a/app/src/main/java/io/xpipe/app/core/AppProperties.java +++ b/app/src/main/java/io/xpipe/app/core/AppProperties.java @@ -41,7 +41,9 @@ public class AppProperties { } }); - fullVersion = Optional.ofNullable(props.getProperty("io.xpipe.app.fullVersion")).map(Boolean::parseBoolean).orElse(false); + fullVersion = Optional.ofNullable(props.getProperty("io.xpipe.app.fullVersion")) + .map(Boolean::parseBoolean) + .orElse(false); version = Optional.ofNullable(props.getProperty("version")).orElse("dev"); build = Optional.ofNullable(props.getProperty("build")).orElse("unknown"); buildUuid = Optional.ofNullable(System.getProperty("io.xpipe.app.buildId")) diff --git a/app/src/main/java/io/xpipe/app/issue/SentryErrorHandler.java b/app/src/main/java/io/xpipe/app/issue/SentryErrorHandler.java index 1818355b..c61f1306 100644 --- a/app/src/main/java/io/xpipe/app/issue/SentryErrorHandler.java +++ b/app/src/main/java/io/xpipe/app/issue/SentryErrorHandler.java @@ -14,6 +14,7 @@ import java.util.Date; public class SentryErrorHandler { public static void init() { + AppProperties.init(); if (AppProperties.get().getSentryUrl() != null) { Sentry.init(options -> { options.setDsn(AppProperties.get().getSentryUrl()); @@ -24,6 +25,7 @@ public class SentryErrorHandler { options.setRelease(AppProperties.get().getVersion()); options.setEnableShutdownHook(false); options.setProguardUuid(AppProperties.get().getBuildUuid().toString()); + options.setTag("os", System.getProperty("os.name")); }); } diff --git a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java index 1d416983..c6f5dbf7 100644 --- a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java +++ b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java @@ -4,6 +4,7 @@ import io.sentry.Sentry; import io.xpipe.app.core.*; import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.update.AppUpdater; +import io.xpipe.app.util.Hyperlinks; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.ButtonBar; @@ -86,24 +87,23 @@ public class TerminalErrorHandler implements ErrorHandler { private static void handleProbableUpdate() { try { - AppUpdater.initFallback(); + AppUpdater.init(); var rel = AppUpdater.get().checkForUpdate(true); if (rel.isUpdate()) { var update = AppWindowHelper.showBlockingAlert(alert -> { alert.setAlertType(Alert.AlertType.INFORMATION); alert.setTitle(AppI18n.get("updateAvailableTitle")); - alert.setHeaderText(AppI18n.get("updateAvailableHeader")); + alert.setHeaderText(AppI18n.get("updateAvailableHeader", rel.getVersion())); alert.getDialogPane() .setContent(AppWindowHelper.alertContentText(AppI18n.get("updateAvailableContent"))); alert.getButtonTypes().clear(); - alert.getButtonTypes().add(new ButtonType(AppI18n.get("install"), ButtonBar.ButtonData.YES)); + alert.getButtonTypes().add(new ButtonType(AppI18n.get("checkOutUpdate"), ButtonBar.ButtonData.YES)); alert.getButtonTypes().add(new ButtonType(AppI18n.get("ignore"), ButtonBar.ButtonData.NO)); }) .map(buttonType -> buttonType.getButtonData().isDefaultButton()) .orElse(false); if (update) { - AppUpdater.get().downloadUpdate(); - AppUpdater.get().executeUpdateAndClose(); + Hyperlinks.open(rel.getReleaseUrl()); } } } catch (Throwable t) { diff --git a/app/src/main/java/io/xpipe/app/launcher/LauncherInput.java b/app/src/main/java/io/xpipe/app/launcher/LauncherInput.java index 25f63047..672adb34 100644 --- a/app/src/main/java/io/xpipe/app/launcher/LauncherInput.java +++ b/app/src/main/java/io/xpipe/app/launcher/LauncherInput.java @@ -1,12 +1,9 @@ package io.xpipe.app.launcher; -import io.xpipe.app.comp.source.GuiDsCreatorMultiStep; import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.ext.ActionProvider; -import io.xpipe.app.ext.DataSourceProvider; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.TrackEvent; -import io.xpipe.core.impl.FileStore; import lombok.Getter; import lombok.Value; @@ -117,7 +114,7 @@ public abstract class LauncherInput { return; } - GuiDsCreatorMultiStep.showForStore(DataSourceProvider.Category.STREAM, FileStore.local(file), null); + // GuiDsCreatorMultiStep.showForStore(DataSourceProvider.Category.STREAM, FileStore.local(file), null); } @Override diff --git a/app/src/main/java/io/xpipe/app/update/AppDownloads.java b/app/src/main/java/io/xpipe/app/update/AppDownloads.java index d671da56..596f9b1d 100644 --- a/app/src/main/java/io/xpipe/app/update/AppDownloads.java +++ b/app/src/main/java/io/xpipe/app/update/AppDownloads.java @@ -107,7 +107,7 @@ public class AppDownloads { var repo = getRepository(); // Always choose most up-to-date release as we assume that there are only full releases and prereleases - if (AppPrefs.get().updateToPrereleases().get()) { + if (AppPrefs.get() != null && AppPrefs.get().updateToPrereleases().get()) { return Optional.ofNullable(repo.listReleases().iterator().next()); } diff --git a/app/src/main/java/io/xpipe/app/update/AppUpdater.java b/app/src/main/java/io/xpipe/app/update/AppUpdater.java index 897b14d0..2f519374 100644 --- a/app/src/main/java/io/xpipe/app/update/AppUpdater.java +++ b/app/src/main/java/io/xpipe/app/update/AppUpdater.java @@ -1,7 +1,6 @@ package io.xpipe.app.update; import io.xpipe.app.core.AppCache; -import io.xpipe.app.core.AppExtensionManager; import io.xpipe.app.core.AppProperties; import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.issue.ErrorEvent; @@ -10,8 +9,6 @@ import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.util.BusyProperty; import io.xpipe.app.util.ThreadHelper; import io.xpipe.app.util.XPipeDistributionType; -import io.xpipe.core.process.ProcessControlProvider; -import io.xpipe.core.util.XPipeSession; import javafx.beans.property.BooleanProperty; import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; @@ -91,16 +88,6 @@ public class AppUpdater { return INSTANCE; } - public static void initFallback() { - AppProperties.init(); - XPipeSession.init(AppProperties.get().getBuildUuid()); - - AppExtensionManager.init(false); - ProcessControlProvider.init(AppExtensionManager.getInstance().getExtendedLayer()); - - INSTANCE = new AppUpdater(); - } - public static void init() { if (INSTANCE != null) { return; @@ -174,7 +161,9 @@ public class AppUpdater { event("Performing update download ..."); try { var downloadFile = AppDownloads.downloadInstaller( - lastUpdateCheckResult.getValue().getAssetType(), lastUpdateCheckResult.getValue().version, false); + lastUpdateCheckResult.getValue().getAssetType(), + lastUpdateCheckResult.getValue().version, + false); if (downloadFile.isEmpty()) { return; } diff --git a/app/src/main/java/io/xpipe/app/util/Hyperlinks.java b/app/src/main/java/io/xpipe/app/util/Hyperlinks.java index c0ecfe4c..292bf488 100644 --- a/app/src/main/java/io/xpipe/app/util/Hyperlinks.java +++ b/app/src/main/java/io/xpipe/app/util/Hyperlinks.java @@ -1,11 +1,7 @@ package io.xpipe.app.util; -import io.xpipe.app.core.App; import io.xpipe.app.issue.ErrorEvent; -import java.awt.*; -import java.net.URI; - public class Hyperlinks { public static final String WEBSITE = "https://xpipe.io"; @@ -16,23 +12,41 @@ public class Hyperlinks { "https://join.slack.com/t/x-pipe/shared_invite/zt-1awjq0t5j-5i4UjNJfNe1VN4b_auu6Cg"; public static final String DOCS_PRIVACY = "https://xpipe.io/docs/privacy"; - public static Runnable openLink(String s) { - return () -> open(s); - } + static final String[] browsers = { + "xdg-open", + "google-chrome", + "firefox", + "opera", + "konqueror", + "mozilla" + }; - public static void open(String url) { - var t = new Thread(() -> { - try { - if (App.getApp() != null) { - App.getApp().getHostServices().showDocument(url); - } else { - Desktop.getDesktop().browse(URI.create(url)); + @SuppressWarnings("deprecation") + public static void open(String uri) { + String osName = System.getProperty("os.name"); + try { + if (osName.startsWith("Mac OS")) { + Runtime.getRuntime().exec( + "open " + uri); + } else if (osName.startsWith("Windows")) { + Runtime.getRuntime().exec( + "rundll32 url.dll,FileProtocolHandler " + uri); + } else { //assume Unix or Linux + String browser = null; + for (String b : browsers) { + if (browser == null && Runtime.getRuntime().exec( + new String[]{"which", b}).getInputStream().read() != -1) { + Runtime.getRuntime().exec(new String[]{browser = b, uri}); + } + } + if (browser == null) { + throw new Exception("No web browser found"); } - } catch (Exception e) { - ErrorEvent.fromThrowable(e).build().handle(); } - }); - t.setDaemon(true); - t.start(); + } catch (Exception e) { + // should not happen + // dump stack for debug purpose + ErrorEvent.fromThrowable(e).handle(); + } } } diff --git a/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties b/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties index ca457380..ad87738a 100644 --- a/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties +++ b/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties @@ -58,8 +58,8 @@ updateReadyAlertHeader=An update to version $VERSION$ is ready to be installed updateReadyAlertContent=This will install the new version and restart X-Pipe once the installation finished. errorNoDetail=No error details are available updateAvailableTitle=Update Available -updateAvailableHeader=An X-Pipe update is available to install -updateAvailableContent=Even though X-Pipe could not be started, you can attempt to install the update to potentially fix the underlying issue. +updateAvailableHeader=An X-Pipe update to version $VERSION$ is available to install +updateAvailableContent=Even though X-Pipe could not be started, you can attempt to install the update to potentially fix the issue. clipboardActionDetectedTitle=Clipboard Action detected clipboardActionDetectedHeader=Do you want to import your clipboard content? clipboardActionDetectedContent=X-Pipe detected content in your clipboard that can be opened. Do you want to open it now? diff --git a/dist/changelogs/0.5.19.md b/dist/changelogs/0.5.19.md new file mode 100644 index 00000000..5a75b756 --- /dev/null +++ b/dist/changelogs/0.5.19.md @@ -0,0 +1 @@ +- Fix shell detection on macOS \ No newline at end of file diff --git a/version b/version index d2d81b78..aa49d36a 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.5.18 \ No newline at end of file +0.5.19 \ No newline at end of file