From 17057e8f8dfaf2e1521cc57d8635d4cf2398e7f1 Mon Sep 17 00:00:00 2001 From: Siard Date: Tue, 2 Jan 2024 10:11:48 +0100 Subject: [PATCH 1/2] Add Google Drive presets improvement. cryptomator/2921 - The code now defaults to searching through '~/Library/CloudStorage/GoogleDrive-*/*' before using the fallback options. --- .../GoogleDriveLocationPresetsProvider.java | 94 ++++++++++++++++--- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java index 970bea042..921201575 100644 --- a/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java +++ b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java @@ -3,39 +3,105 @@ package org.cryptomator.common.locationpresets; import org.cryptomator.integrations.common.CheckAvailability; import org.cryptomator.integrations.common.OperatingSystem; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Pattern; import java.util.stream.Stream; import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC; -import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS; -@OperatingSystem(WINDOWS) @OperatingSystem(MAC) -@CheckAvailability public final class GoogleDriveLocationPresetsProvider implements LocationPresetsProvider { + private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/Library/CloudStorage/").toAbsolutePath(); + private static final Predicate PATTERN = Pattern.compile("^GoogleDrive-[^/]+$").asMatchPredicate(); - private static final List LOCATIONS = Arrays.asList( // + private static final List FALLBACK_LOCATIONS = Arrays.asList( // LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), // LocationPresetsProvider.resolveLocation("~/Google Drive/My Drive"), // LocationPresetsProvider.resolveLocation("~/GoogleDrive"), // LocationPresetsProvider.resolveLocation("~/Google Drive") // ); - @CheckAvailability - public static boolean isPresent() { - return LOCATIONS.stream().anyMatch(Files::isDirectory); - } - @Override public Stream getLocations() { - return LOCATIONS.stream() // - .filter(Files::isDirectory) // - .map(location -> new LocationPreset("Google Drive", location)) // - .findFirst() // - .stream(); + if(isLocationPresent()) { + return getCloudStorageDirLocations(); + } else if(FALLBACK_LOCATIONS.stream().anyMatch(Files::isDirectory)) { + return getFallbackLocation(); + } else { + return Stream.of(); + } } + @CheckAvailability + public static boolean isPresent() { + return isLocationPresent() || FALLBACK_LOCATIONS.stream().anyMatch(Files::isDirectory); + } + + public static boolean isLocationPresent() { + try (DirectoryStream stream = Files.newDirectoryStream(LOCATION, "GoogleDrive-*")) { + return stream.iterator().hasNext(); + } catch (IOException e) { + return false; + } + } + + /** + * Returns Google Drive preset String. + * + * @param accountPath The path to the Google Drive account directory (e.g. {@code ~/Library/CloudStorage/GoogleDrive-username}) + * @param drivePath The path to the Google Drive file directory, within the account directory. (e.g. {@code ~/Library/CloudStorage/GoogleDrive-username/drive_name}) + * @return {@code String}. For example: "Google Drive - username - drive_name" + */ + private String getDriveLocationString(Path accountPath, Path drivePath) { + String accountName = accountPath.getFileName().toString().replace("GoogleDrive-", ""); + String driveName = drivePath.getFileName().toString(); + + return STR."Google Drive - \{accountName} - \{driveName}"; + } + + /** + * Handles searching through {@code ~/Library/CloudStorage/} for directories with the "{@code GoogleDrive-*}" pattern, + * and returns the corresponding presets. + * + * @return {@code Stream}. Displays as "{@code Google Drive - username - drive_name}" + */ + private Stream getCloudStorageDirLocations() { + try (var dirStream = Files.list(LOCATION)) { + var presets = dirStream.filter(path -> Files.isDirectory(path) && PATTERN.test(path.getFileName().toString())) + .flatMap(accountPath -> { + try { + return Files.list(accountPath) + .filter(Files::isDirectory) + .map(drivePath -> new LocationPreset(getDriveLocationString(accountPath, drivePath), drivePath)); + } catch (IOException e) { + throw new RuntimeException(e); + } + }).toList(); + return presets.stream(); + } + catch (IOException | UncheckedIOException e) { + return Stream.of(); + } + } + + /** + * Uses {@code FALLBACK_LOCATIONS} for directories as fallback, if {@code ~/Library/CloudStorage/} isn't present. + * Returns the corresponding presets. + * + * @return {@code Stream}. Displays as "{@code Google Drive}" + */ + private Stream getFallbackLocation() { + return FALLBACK_LOCATIONS.stream() // + .filter(Files::isDirectory) // + .map(location -> new LocationPreset("Google Drive", location)) + .findFirst() + .stream(); + } } From d85c6c8f41ebbc3ed861dcc43c9203830bba1697 Mon Sep 17 00:00:00 2001 From: Siard Date: Tue, 2 Jan 2024 10:20:18 +0100 Subject: [PATCH 2/2] Create separate files for GoogleDrive presets providers. cryptomator/2921 - Change imports accordingly in module-info.java --- src/main/java/module-info.java | 5 ++- ...oogleDriveMacLocationPresetsProvider.java} | 2 +- ...leDriveWindowsLocationPresetsProvider.java | 38 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) rename src/main/java/org/cryptomator/common/locationpresets/{GoogleDriveLocationPresetsProvider.java => GoogleDriveMacLocationPresetsProvider.java} (97%) create mode 100644 src/main/java/org/cryptomator/common/locationpresets/GoogleDriveWindowsLocationPresetsProvider.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index b353b7a8a..bf318ab80 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,7 +2,8 @@ import ch.qos.logback.classic.spi.Configurator; import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider; import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider; -import org.cryptomator.common.locationpresets.GoogleDriveLocationPresetsProvider; +import org.cryptomator.common.locationpresets.GoogleDriveMacLocationPresetsProvider; +import org.cryptomator.common.locationpresets.GoogleDriveWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider; import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.LeitzcloudLocationPresetsProvider; @@ -56,7 +57,7 @@ open module org.cryptomator.desktop { provides Configurator with LogbackConfiguratorFactory; provides LocationPresetsProvider with // DropboxWindowsLocationPresetsProvider, DropboxMacLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, // - GoogleDriveLocationPresetsProvider, // + GoogleDriveMacLocationPresetsProvider, GoogleDriveWindowsLocationPresetsProvider, // ICloudWindowsLocationPresetsProvider, ICloudMacLocationPresetsProvider, // LeitzcloudLocationPresetsProvider, // MegaLocationPresetsProvider, // diff --git a/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveMacLocationPresetsProvider.java similarity index 97% rename from src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java rename to src/main/java/org/cryptomator/common/locationpresets/GoogleDriveMacLocationPresetsProvider.java index 921201575..8aa32b91c 100644 --- a/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveLocationPresetsProvider.java +++ b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveMacLocationPresetsProvider.java @@ -17,7 +17,7 @@ import java.util.stream.Stream; import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC; @OperatingSystem(MAC) -public final class GoogleDriveLocationPresetsProvider implements LocationPresetsProvider { +public final class GoogleDriveMacLocationPresetsProvider implements LocationPresetsProvider { private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/Library/CloudStorage/").toAbsolutePath(); private static final Predicate PATTERN = Pattern.compile("^GoogleDrive-[^/]+$").asMatchPredicate(); diff --git a/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveWindowsLocationPresetsProvider.java b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveWindowsLocationPresetsProvider.java new file mode 100644 index 000000000..fea1632c4 --- /dev/null +++ b/src/main/java/org/cryptomator/common/locationpresets/GoogleDriveWindowsLocationPresetsProvider.java @@ -0,0 +1,38 @@ +package org.cryptomator.common.locationpresets; + +import org.cryptomator.integrations.common.CheckAvailability; +import org.cryptomator.integrations.common.OperatingSystem; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS; + +@OperatingSystem(WINDOWS) +@CheckAvailability +public final class GoogleDriveWindowsLocationPresetsProvider implements LocationPresetsProvider { + + private static final List LOCATIONS = Arrays.asList( // + LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive"), // + LocationPresetsProvider.resolveLocation("~/Google Drive/My Drive"), // + LocationPresetsProvider.resolveLocation("~/GoogleDrive"), // + LocationPresetsProvider.resolveLocation("~/Google Drive") // + ); + + @CheckAvailability + public static boolean isPresent() { + return LOCATIONS.stream().anyMatch(Files::isDirectory); + } + + @Override + public Stream getLocations() { + return LOCATIONS.stream() // + .filter(Files::isDirectory) // + .map(location -> new LocationPreset("Google Drive", location)) // + .findFirst() // + .stream(); + } +}