瀏覽代碼

Merge branch 'develop' into feature/hub

Sebastian Stenzel 3 年之前
父節點
當前提交
3cd99f680a

+ 8 - 10
.github/workflows/release.yml

@@ -39,15 +39,11 @@ jobs:
           profile: mac
     steps:
       - uses: actions/checkout@v2
-      - uses: actions/setup-java@v1
+      - uses: actions/setup-java@v2
         with:
+          distribution: 'temurin'
           java-version: ${{ env.JAVA_VERSION }}
-      - uses: actions/cache@v2
-        with:
-          path: ~/.m2/repository
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
+          cache: 'maven'
       - name: Ensure to use tagged version
         run: mvn versions:set -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
         if: startsWith(github.ref, 'refs/tags/')
@@ -159,8 +155,9 @@ jobs:
             --resource-dir dist/mac/resources
     steps:
       - uses: actions/checkout@v2
-      - uses: actions/setup-java@v1
+      - uses: actions/setup-java@v2
         with:
+          distribution: 'temurin'
           java-version: ${{ env.JAVA_VERSION }}
       - name: Download ${{ matrix.profile }}-buildkit
         uses: actions/download-artifact@v2
@@ -210,7 +207,7 @@ jobs:
   ppa:
     name: Upload source package to PPA
     needs: [buildkit, metadata]
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-18.04
     steps:
       - uses: actions/checkout@v2
       - name: install build tools
@@ -505,8 +502,9 @@ jobs:
           name: win-appdir
       - name: Untar appdir.tar
         run: tar -xvf appdir.tar
-      - uses: actions/setup-java@v1
+      - uses: actions/setup-java@v2
         with:
+          distribution: 'temurin'
           java-version: ${{ env.JAVA_VERSION }}
       - name: Patch Application Directory
         run: |

+ 8 - 0
README.md

@@ -28,6 +28,14 @@ Cryptomator is provided free of charge as an open-source project despite the hig
 
 ### Silver Sponsors
 
+<table>
+  <tbody>
+    <tr>
+      <td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="40"></a></td>
+    </tr>
+  </tbody>
+</table>
+
 - [Jameson Lopp](https://www.lopp.net/)
 
 ---

+ 1 - 1
dist/linux/debian/changelog

@@ -1,4 +1,4 @@
-cryptomator (${PPA_VERSION}) focal; urgency=low
+cryptomator (${PPA_VERSION}) bionic; urgency=low
 
   * Full changelog can be found on https://github.com/cryptomator/cryptomator/releases
 

+ 2 - 1
dist/mac/dmg/.gitignore

@@ -1,3 +1,4 @@
 # created during build
 runtime/
-*.app/
+dmg/
+*.dmg

+ 27 - 1
dist/mac/dmg/build.sh

@@ -16,13 +16,14 @@ shift "$((OPTIND-1))"
 
 # prepare working dir and variables
 cd $(dirname $0)
-rm -rf runtime *.app
+rm -rf runtime dmg
 REVISION_NO=`git rev-list --count HEAD`
 VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
 
 # check preconditions
 if [ -z "${JAVA_HOME}" ]; then echo "JAVA_HOME not set. Run using JAVA_HOME=/path/to/jdk ./build.sh"; exit 1; fi
 command -v mvn >/dev/null 2>&1 || { echo >&2 "mvn not found."; exit 1; }
+command -v create-dmg >/dev/null 2>&1 || { echo >&2 "create-dmg not found."; exit 1; }
 if [ -n "${CODESIGN_IDENTITY}" ]; then
     command -v codesign >/dev/null 2>&1 || { echo >&2 "codesign not found. Fix by 'xcode-select --install'."; exit 1; }
     if [[ ! `security find-identity -v -p codesigning | grep -w "${CODESIGN_IDENTITY}"` ]]; then echo "Given codesign identity is invalid."; exit 1; fi
@@ -59,6 +60,7 @@ ${JAVA_HOME}/bin/jpackage \
     --java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
     --app-version "${VERSION_NO}" \
     --java-options "-Dfile.encoding=\"utf-8\"" \
+    --java-options "-Dapple.awt.enableTemplateImages=true" \
     --java-options "-Dcryptomator.logDir=\"~/Library/Logs/Cryptomator\"" \
     --java-options "-Dcryptomator.pluginDir=\"~/Library/Application Support/Cryptomator/Plugins\"" \
     --java-options "-Dcryptomator.settingsPath=\"~/Library/Application Support/Cryptomator/settings.json\"" \
@@ -94,3 +96,27 @@ if [ -n "${CODESIGN_IDENTITY}" ]; then
     echo "Codesigning Cryptomator.app..."
     codesign --force --deep --entitlements ../Cryptomator.entitlements -o runtime -s ${CODESIGN_IDENTITY} Cryptomator.app
 fi
+
+# prepare dmg contents
+mkdir dmg
+mv Cryptomator.app dmg
+cp resources/macFUSE.webloc dmg
+
+# create dmg
+create-dmg \
+    --volname Cryptomator \
+    --volicon "resources/Cryptomator-Volume.icns" \
+    --background "resources/Cryptomator-background.tiff" \
+    --window-pos 400 100 \
+    --window-size 640 694 \
+    --icon-size 128 \
+    --icon "Cryptomator.app" 128 245 \
+    --hide-extension "Cryptomator.app" \
+    --icon "macFUSE.webloc" 320 501 \
+    --hide-extension "macFUSE.webloc" \
+    --app-drop-link 512 245 \
+    --eula "resources/license.rtf" \
+    --icon ".background" 128 758 \
+    --icon ".fseventsd" 320 758 \
+    --icon ".VolumeIcon.icns" 512 758 \
+    Cryptomator-${VERSION_NO}.dmg dmg

+ 3 - 0
dist/win/.gitignore

@@ -0,0 +1,3 @@
+runtime
+Cryptomator
+installer

+ 2 - 0
dist/win/build.bat

@@ -0,0 +1,2 @@
+@echo off
+powershell -NoExit -ExecutionPolicy Unrestricted -Command .\build.ps1

+ 91 - 0
dist/win/build.ps1

@@ -0,0 +1,91 @@
+# check preconditions
+if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null) 
+{ 
+   Write-Host "Unable to find git.exe in your PATH (try: choco install git)"
+   exit 1
+}
+if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null) 
+{ 
+   Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)"
+   exit 1
+}
+
+$buildDir = Split-Path -Parent $PSCommandPath
+$version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout)
+$semVerNo = $version -replace '(\d\.\d\.\d).*','$1'
+$revisionNo = $(git rev-list --count HEAD)
+
+Write-Output "`$version=$version"
+Write-Output "`$semVerNo=$semVerNo"
+Write-Output "`$revisionNo=$revisionNo"
+Write-Output "`$buildDir=$buildDir"
+Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
+
+# compile
+&mvn -B -f $buildDir/../../pom.xml clean package -DskipTests -Pwin
+Copy-Item "$buildDir\..\..\target\cryptomator-*.jar" -Destination "$buildDir\..\..\target\mods"
+
+# add runtime
+& "$Env:JAVA_HOME\bin\jlink" `
+	--verbose `
+	--output runtime `
+	--module-path "$Env:JAVA_HOME/jmods" `
+	--add-modules java.base,java.desktop,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility `
+	--no-header-files `
+	--no-man-pages `
+	--strip-debug `
+	--compress=1
+
+# create app dir
+& "$Env:JAVA_HOME\bin\jpackage" `
+	--verbose `
+	--type app-image `
+	--runtime-image runtime `
+	--input ../../target/libs `
+	--module-path ../../target/mods `
+	--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator `
+	--dest . `
+	--name Cryptomator `
+	--vendor "Skymatic GmbH" `
+	--copyright "(C) 2016 - 2021 Skymatic GmbH" `
+	--java-options "-Xss5m" `
+	--java-options "-Xmx256m" `
+	--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
+	--app-version "$semVerNo.$revisionNo" `
+	--java-options "-Dfile.encoding=`"utf-8`"" `
+	--java-options "-Dcryptomator.logDir=`"~/AppData/Roaming/Cryptomator`"" `
+	--java-options "-Dcryptomator.pluginDir=`"~/AppData/Roaming/Cryptomator/Plugins`"" `
+	--java-options "-Dcryptomator.settingsPath=`"~/AppData/Roaming/Cryptomator/settings.json`"" `
+	--java-options "-Dcryptomator.ipcSocketPath=`"~/AppData/Roaming/Cryptomator/ipc.socket`"" `
+	--java-options "-Dcryptomator.keychainPath=`"~/AppData/Roaming/Cryptomator/keychain.json`"" `
+	--java-options "-Dcryptomator.mountPointsDir=`"~/Cryptomator`"" `
+	--java-options "-Dcryptomator.showTrayIcon=true" `
+	--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
+	--resource-dir resources `
+	--icon resources/Cryptomator.ico
+
+# patch app dir
+Copy-Item "contrib\*" -Destination "Cryptomator"
+attrib -r "Cryptomator\Cryptomator.exe"
+
+
+# create .msi bundle
+$Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
+& "$Env:JAVA_HOME\bin\jpackage" `
+	--verbose `
+	--type msi `
+	--win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775 `
+	--app-image Cryptomator `
+	--dest installer `
+	--name Cryptomator `
+	--vendor "Skymatic GmbH" `
+	--copyright "(C) 2016 - 2021 Skymatic GmbH" `
+	--app-version "$semVerNo" `
+	--win-menu `
+	--win-dir-chooser `
+	--win-shortcut-prompt `
+	--win-update-url "https:\\cryptomator.org" `
+	--win-menu-group Cryptomator `
+	--resource-dir resources `
+	--license-file resources/license.rtf `
+	--file-associations resources/FAvaultFile.properties

+ 5 - 1
src/main/java/org/cryptomator/ui/common/UserInteractionLock.java

@@ -16,7 +16,11 @@ public class UserInteractionLock<E extends Enum> {
 	private volatile E state;
 
 	public UserInteractionLock(E initialValue) {
-		state = initialValue;
+		this.state = initialValue;
+	}
+
+	public synchronized void reset(E value) {
+		this.state = value;
 	}
 
 	public void interacted(E result) {

+ 11 - 1
src/main/java/org/cryptomator/ui/lock/LockForcedController.java

@@ -35,7 +35,13 @@ public class LockForcedController implements FxController {
 	}
 
 	@FXML
-	public void confirmForcedLock() {
+	public void retry() {
+		forceLockDecisionLock.interacted(LockModule.ForceLockDecision.RETRY);
+		window.close();
+	}
+
+	@FXML
+	public void force() {
 		forceLockDecisionLock.interacted(LockModule.ForceLockDecision.FORCE);
 		window.close();
 	}
@@ -54,4 +60,8 @@ public class LockForcedController implements FxController {
 		return vault.getDisplayName();
 	}
 
+	public boolean isForceSupported() {
+		return vault.supportsForcedUnmount();
+	}
+
 }

+ 1 - 0
src/main/java/org/cryptomator/ui/lock/LockModule.java

@@ -28,6 +28,7 @@ abstract class LockModule {
 
 	enum ForceLockDecision {
 		CANCEL,
+		RETRY,
 		FORCE;
 	}
 

+ 10 - 4
src/main/java/org/cryptomator/ui/lock/LockWorkflow.java

@@ -51,20 +51,26 @@ public class LockWorkflow extends Task<Void> {
 
 	@Override
 	protected Void call() throws Volume.VolumeException, InterruptedException, LockNotCompletedException {
+		lock(false);
+		return null;
+	}
+
+	private void lock(boolean forced) throws InterruptedException {
 		try {
-			vault.lock(false);
+			vault.lock(forced);
 		} catch (Volume.VolumeException | LockNotCompletedException e) {
-			LOG.debug("Regular lock of {} failed.", vault.getDisplayName(), e);
+			LOG.info("Locking {} failed (forced: {}).", vault.getDisplayName(), forced, e);
 			var decision = askUserForAction();
 			switch (decision) {
-				case FORCE -> vault.lock(true);
+				case RETRY -> lock(false);
+				case FORCE -> lock(true);
 				case CANCEL -> cancel(false);
 			}
 		}
-		return null;
 	}
 
 	private LockModule.ForceLockDecision askUserForAction() throws InterruptedException {
+		forceLockDecisionLock.reset(null);
 		// show forcedLock dialogue ...
 		Platform.runLater(() -> {
 			lockWindow.setScene(lockForcedScene.get());

+ 2 - 2
src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java

@@ -34,10 +34,10 @@ public class SupporterCertificateController implements FxController {
 	public void initialize() {
 		supporterCertificateField.setText(licenseHolder.getLicenseKey().orElse(null));
 		supporterCertificateField.textProperty().addListener(this::registrationKeyChanged);
-		supporterCertificateField.setTextFormatter(new TextFormatter<>(this::checkVaultNameLength));
+		supporterCertificateField.setTextFormatter(new TextFormatter<>(this::removeWhitespaces));
 	}
 
-	private TextFormatter.Change checkVaultNameLength(TextFormatter.Change change) {
+	private TextFormatter.Change removeWhitespaces(TextFormatter.Change change) {
 		if (change.isContentChange()) {
 			var strippedText = CharMatcher.whitespace().removeFrom(change.getText());
 			change.setText(strippedText);

+ 2 - 2
src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java

@@ -47,7 +47,7 @@ public class GeneralVaultOptionsController implements FxController {
 	public void initialize() {
 		vaultName.textProperty().set(vault.getVaultSettings().displayName().get());
 		vaultName.focusedProperty().addListener(this::trimVaultNameOnFocusLoss);
-		vaultName.setTextFormatter(new TextFormatter<>(this::removeWhitespaces));
+		vaultName.setTextFormatter(new TextFormatter<>(this::checkVaultNameLength));
 		unlockOnStartupCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().unlockAfterStartup());
 		actionAfterUnlockChoiceBox.getItems().addAll(WhenUnlocked.values());
 		actionAfterUnlockChoiceBox.valueProperty().bindBidirectional(vault.getVaultSettings().actionAfterUnlock());
@@ -63,7 +63,7 @@ public class GeneralVaultOptionsController implements FxController {
 		}
 	}
 
-	private TextFormatter.Change removeWhitespaces(TextFormatter.Change change) {
+	private TextFormatter.Change checkVaultNameLength(TextFormatter.Change change) {
 		if (change.isContentChange() && change.getControlNewText().length() > VAULTNAME_TRUNCATE_THRESHOLD) {
 			return null; // reject any change that would lead to a text exceeding threshold
 		} else {

+ 3 - 3
src/main/resources/fxml/lock_forced.fxml

@@ -33,11 +33,11 @@
 		</HBox>
 
 		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
-			<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
+			<ButtonBar buttonMinWidth="100" buttonOrder="+CIU">
 				<buttons>
 					<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" cancelButton="true" onAction="#cancel"/>
-					<!-- TODO: third button with retry? -->
-					<Button text="%lock.forced.confirmBtn" ButtonBar.buttonData="FINISH" onAction="#confirmForcedLock"/>
+					<Button text="%lock.forced.retryBtn" ButtonBar.buttonData="FINISH" onAction="#retry"/>
+					<Button text="%lock.forced.forceBtn" ButtonBar.buttonData="OTHER" onAction="#force" disable="${!controller.forceSupported}"/>
 				</buttons>
 			</ButtonBar>
 		</VBox>

+ 3 - 2
src/main/resources/i18n/strings.properties

@@ -118,9 +118,10 @@ unlock.error.invalidMountPoint.existing=Mount point "%s" already exists or paren
 
 # Lock
 ## Force
-lock.forced.heading=Graceful lock failed
+lock.forced.heading=Lock failed
 lock.forced.message=Locking "%s" was blocked by pending operations or open files. You can force lock this vault, however interrupting I/O may result in the loss of unsaved data.
-lock.forced.confirmBtn=Force Lock
+lock.forced.retryBtn=Retry
+lock.forced.forceBtn=Force Lock
 ## Failure
 lock.fail.heading=Locking vault failed.
 lock.fail.message=Vault "%s" could not be locked. Ensure unsaved work is saved elsewhere and important Read/Write operations are finished. In order to close the vault, kill the Cryptomator process.