Compare commits

..
Author SHA1 Message Date
Armin Schrenk 1dab85d265 Merge branch 'develop' into release/1.19.0 2026-02-18 16:25:04 +01:00
Armin Schrenk 423752e720 [skip ci] update changelog 2026-02-18 16:22:31 +01:00
CryptobotandGitHub 4efcec7e93 New Crowdin updates (#4041)
New translations strings.properties

Afrikaans; Arabic; Bashkir; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Marathi; Norwegian; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Urdu (Pakistan); Uyghur; Vietnamese; 

[ci skip]
2026-02-18 15:56:30 +01:00
Armin Schrenk 619d981ded [skip ci] Update README 2026-02-18 15:46:47 +01:00
mindmonkandGitHub 72d93e943b fix text wrapping in ResetPasswordDialog (#4123) 2026-02-18 15:43:50 +01:00
Armin SchrenkandGitHub f07523267d Bump javafx to version 25.0.2 (#4145) 2026-02-18 15:42:51 +01:00
Armin Schrenk 5409470750 update wix 2026-02-18 15:27:36 +01:00
Armin Schrenk 70b7f39bcc revert 5ab12c1b1a for windows build 2026-02-18 15:16:39 +01:00
Armin Schrenk 5ab12c1b1a Update to latest JDK 25 2026-02-18 11:49:13 +01:00
Armin Schrenk 0ac63e7aba Closes #4136 2026-02-18 11:26:42 +01:00
Armin Schrenk ac6f34fe17 reorder changelog 2026-02-18 11:15:46 +01:00
Armin Schrenk dba3de230b Update dependencies
* org.cryptomator:integrations-win from 1.5.1 to 1.6.0
* org.cryptomator:webdav-nio-adapter from 3.0.0 to 3.0.1
2026-02-18 11:15:00 +01:00
Armin Schrenk e11d42bb07 update IDE file 2026-02-18 11:07:18 +01:00
Jan-Peter Klein 171d5d5a4c Fixes #4141 2026-02-18 10:55:49 +01:00
Armin Schrenk b86d8ca790 [skip ci] update changelog 2026-02-17 15:30:20 +01:00
Armin Schrenk 74fc77ab8d fix pom inconsistency 2026-02-17 15:21:16 +01:00
Armin Schrenk 044dbcb11f Update cryptofs to version 2.10.0-beta3 2026-02-17 15:13:46 +01:00
Armin Schrenk 1b243bb725 suppress logging of expected exception 2026-02-17 15:12:25 +01:00
Armin SchrenkandGitHub f21cb90e7d Merge pull request #4025 from purejava/new-secret-service
New keychain backend SecretService for Linux
2026-02-17 13:16:06 +01:00
Armin SchrenkandGitHub 1e8f272f6a Merge pull request #4143 from cryptomator/dependabot/maven/java-production-dependencies-d98826387a
Bump the java-production-dependencies group across 1 directory with 11 updates
2026-02-17 13:15:07 +01:00
Armin Schrenk 5c1f8e7576 update IDE file 2026-02-17 12:46:19 +01:00
Armin Schrenk bc0bb38e4c remove dagger formatting due to compile error 2026-02-17 12:45:46 +01:00
Armin SchrenkandGitHub b9b02acbe5 Merge pull request #4134 from cryptomator/feature/javafx-color-scheme-change
Feature: Use JavaFX built ins to adapt to OS color scheme
2026-02-17 10:36:23 +01:00
Armin Schrenk e53598cfce update azure signing to stable version 2026-02-16 17:06:00 +01:00
Armin Schrenk a79fd63634 [skip ci] update changelog 2026-02-16 16:15:05 +01:00
f753ddc9be Apply suggestions from code review
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2026-02-16 16:05:26 +01:00
Armin Schrenk 158b454b0d fix NPE in EventualLogger 2026-02-16 12:45:57 +01:00
Armin Schrenk 9e6bd913cb refactor FxApplicationStyle
use pattern (removeOldListeners, addNewListerner, applyTheme)
2026-02-16 12:37:46 +01:00
Armin Schrenk 83ef9d06d9 simplify JfxUiAppearanceProvider
and move loading of appearance service into the fx app
2026-02-16 11:55:03 +01:00
Armin Schrenk cf0052b4f5 revert lambda processing 2026-02-16 11:07:04 +01:00
Armin Schrenk 0b4d86768a Closes #4088 2026-02-16 10:13:21 +01:00
dependabot[bot]andGitHub a77e90738a Bump the java-production-dependencies group across 1 directory with 11 updates
Bumps the java-production-dependencies group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [org.cryptomator:cryptolib](https://github.com/cryptomator/cryptolib) | `2.2.1` | `2.2.2` |
| [org.cryptomator:fuse-nio-adapter](https://github.com/cryptomator/fuse-nio-adapter) | `5.1.0` | `6.0.0` |
| [ch.qos.logback:logback-core](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| org.apache.commons:commons-lang3 | `3.19.0` | `3.20.0` |
| [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) | `2.20.0` | `2.21.0` |
| com.fasterxml.jackson.datatype:jackson-datatype-jsr310 | `2.20.0` | `2.21.0` |
| [com.google.dagger:dagger](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.google.dagger:dagger-compiler](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) | `3.2.2` | `3.2.3` |
| [org.cryptomator:integrations-linux](https://github.com/cryptomator/integrations-linux) | `1.7.0-beta3` | `1.7.0-beta4` |



Updates `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
- [Release notes](https://github.com/cryptomator/cryptolib/releases)
- [Changelog](https://github.com/cryptomator/cryptolib/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/cryptolib/compare/2.2.1...2.2.2)

Updates `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.0
- [Release notes](https://github.com/cryptomator/fuse-nio-adapter/releases)
- [Changelog](https://github.com/cryptomator/fuse-nio-adapter/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/fuse-nio-adapter/compare/5.1.0...6.0.0)

Updates `ch.qos.logback:logback-core` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.0
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.google.dagger:dagger` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.2.2...v3.2.3)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `org.cryptomator:integrations-linux` from 1.7.0-beta3 to 1.7.0-beta4
- [Release notes](https://github.com/cryptomator/integrations-linux/releases)
- [Changelog](https://github.com/cryptomator/integrations-linux/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-linux/compare/1.7.0-beta3...1.7.0-beta4)

---
updated-dependencies:
- dependency-name: org.cryptomator:cryptolib
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:fuse-nio-adapter
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-core
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-version: 3.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-linux
  dependency-version: 1.7.0-beta4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 06:06:54 +00:00
mindmonkandGitHub 0bec741c2b Merge pull request #4120 from cryptomator/feature/disable-password-tab-if-masterkey-missing
Disable recovery key actions in Vault Password options when masterkey is missing
2026-02-12 18:08:52 +01:00
Armin SchrenkandGitHub af43aeca15 Merge branch 'develop' into feature/javafx-color-scheme-change 2026-02-12 10:18:32 +01:00
Armin Schrenk 1629eae5d3 [skip ci] update changelog 2026-02-11 15:55:34 +01:00
Armin Schrenk 99898b74fb minor cleanup 2026-02-11 15:55:19 +01:00
Armin SchrenkandGitHub 327d6065e9 Merge pull request #4105 from cryptomator/feature/admin-properties
Feature: Admin Config
2026-02-11 15:25:31 +01:00
Armin Schrenk 2a5ef5d999 log inconsistent state 2026-02-11 15:21:55 +01:00
Armin Schrenk 34e5d19a04 prevent resource leak 2026-02-11 15:16:11 +01:00
Armin Schrenk 33851a8559 Refactor admin props
* rename class to AdminPropertiesFactory
* rename factory method to "create"
* remove side effects from methods
* returned properties default to system properties
2026-02-11 15:12:52 +01:00
Armin Schrenk fb54d96997 fix wrong method delegation 2026-02-11 14:49:56 +01:00
Armin Schrenk cff47b1c73 wrap system properties instead of direct modification 2026-02-11 14:36:55 +01:00
Armin Schrenk 5db05d8bc7 Apply suggestions from codereview 2026-02-11 14:33:01 +01:00
Armin Schrenk b85780eae9 Disable JavaFX based UiAppearanceProvider for macOS 2026-02-11 12:22:22 +01:00
Ralph Plawetzki bdfd22c483 Partially reverts https://github.com/cryptomator/cryptomator/commit/dd1af8cd783589e8c8b06e7c4881195e10a67815
Not needed anymore, see https://github.com/cryptomator/integrations-linux/pull/125#issuecomment-3876060158
2026-02-11 06:07:01 +01:00
Armin Schrenk e3433cb312 Refactor FxApplicationStyle class 2026-02-10 18:17:09 +01:00
Armin Schrenk 46d1d605ad refactor JfxUiAppearanceProvider class
* use delegate pattern for initialization
* add logging
2026-02-10 18:01:36 +01:00
Armin Schrenk a4eadd4817 remove theme change restrictions 2026-02-10 17:58:29 +01:00
Armin Schrenk c6717bd4e1 Rely on javafx to change color theme 2026-02-09 17:48:23 +01:00
Armin Schrenk 53f368108a Rename jvm property and actual config file 2026-02-09 16:54:04 +01:00
Armin Schrenk 5e52811c74 Remove hard coded default locations for admin config 2026-02-09 16:49:12 +01:00
Armin Schrenk cad7b45808 Refactor to first check system property cryptomator.adminConfig for config path 2026-02-09 16:16:26 +01:00
Armin Schrenk a057bf6f70 Merge branch 'develop' into feature/admin-properties 2026-02-09 15:03:06 +01:00
Armin Schrenk 4cf11cf293 [skip ci] update changelog 2026-02-09 14:56:37 +01:00
Armin SchrenkandGitHub 2523609996 disable loading of user defined config for windows msi (#4132) 2026-02-09 14:49:07 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
80276ee992 Bump the github-actions group across 1 directory with 8 updates (#4124)
Bumps the github-actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `6.0.1` | `6.0.2` |
| [actions/setup-java](https://github.com/actions/setup-java) | `5.1.0` | `5.2.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `5.0.0` | `6.0.0` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `6.0.0` | `7.0.0` |
| [actions/cache](https://github.com/actions/cache) | `4.3.0` | `5.0.3` |
| [skymatic/workflows/.github/workflows/run-dependency-check.yml](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |
| [fjogeleit/http-request-action](https://github.com/fjogeleit/http-request-action) | `1.16.6` | `2.0.0` |
| [skymatic/workflows](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |



Updates `actions/checkout` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

Updates `actions/setup-java` from 5.1.0 to 5.2.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654)

Updates `actions/upload-artifact` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f)

Updates `actions/download-artifact` from 6.0.0 to 7.0.0
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131)

Updates `actions/cache` from 4.3.0 to 5.0.3
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/0057852bfaa89a56745cba8c7296529d2fc39830...cdf6c1fa76f9f475f3d7449005a359c84ca0f306)

Updates `skymatic/workflows/.github/workflows/run-dependency-check.yml` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](https://github.com/skymatic/workflows/compare/1074588008ae3326a2221ea451783280518f0366...2d0c27a7b04c605afe1ca85e37c0e86517defcc9)

Updates `fjogeleit/http-request-action` from 1.16.6 to 2.0.0
- [Release notes](https://github.com/fjogeleit/http-request-action/releases)
- [Changelog](https://github.com/fjogeleit/http-request-action/blob/main/RELEASE.md)
- [Commits](https://github.com/fjogeleit/http-request-action/compare/c0b95d02a088b47c1f2f4db04fd8af8bd19eee54...551353b829c3646756b2ec2b3694f819d7957495)

Updates `skymatic/workflows` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](https://github.com/skymatic/workflows/compare/1074588008ae3326a2221ea451783280518f0366...2d0c27a7b04c605afe1ca85e37c0e86517defcc9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/cache
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows/.github/workflows/run-dependency-check.yml
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: fjogeleit/http-request-action
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 09:27:49 +01:00
Ralph Plawetzki 561432bc98 Revert "Make SecretServiceKeychainAccess the default selection"
This reverts commit 9a74194391.
Users decide when to migrate.
2026-02-05 08:15:10 +01:00
Ralph Plawetzki cd0a640a36 Enable migrating KeychainEntries on Linux as well 2026-02-05 07:09:38 +01:00
Armin SchrenkandGitHub a7b8541912 Update Slack webhook URL secret in workflow 2026-01-30 15:27:31 +01:00
Jan-Peter Klein d4382f3130 remove docTooltip 2026-01-28 18:40:56 +01:00
Jan-Peter Klein 2983745be5 remove docs link 2026-01-28 18:20:18 +01:00
Armin Schrenk 77983fe00a simplify EventualLogger init 2026-01-28 17:44:48 +01:00
Armin Schrenk a4836f6528 cleanup 2026-01-28 17:36:52 +01:00
Armin Schrenk e9b3b505a8 apply suggestions from code review 2026-01-28 17:35:34 +01:00
Armin Schrenk 19c9eada9d check first the filesize before opening a Reader to the config file 2026-01-28 17:32:10 +01:00
Jan-Peter Klein 2a5bce2c5c disable password tab when masterkey.file is missing 2026-01-27 17:42:04 +01:00
mindmonkandGitHub 9ee81a0e35 Merge pull request #4106 from cryptomator/feature/move-recover-io-tasks-to-background
Move recovery I/O to background thread
2026-01-26 13:30:39 +01:00
Jan-Peter Klein 8b05ae0a54 dedup createTask 2026-01-23 16:09:06 +01:00
Jan-Peter Klein aa898c634f refactor recovery restore to sync logic with async task wrapper for testability 2026-01-23 13:57:38 +01:00
Armin Schrenk efbd107fb5 increase null safety 2026-01-21 18:09:26 +01:00
Armin Schrenk 300cac5441 don't forget log markers 2026-01-21 16:36:56 +01:00
Armin Schrenk b651b9ac26 config file can be exactly the max size 2026-01-21 16:08:00 +01:00
Armin Schrenk 29e76e7f93 keep throwables in EventualLogger 2026-01-21 16:07:17 +01:00
Armin Schrenk 5cac6b8114 also adjust distribution 2026-01-21 15:55:04 +01:00
Armin Schrenk 35c2141fd6 cleanup 2026-01-21 15:34:34 +01:00
Armin Schrenk b00c81c20a use "cryptomator.config" for config file 2026-01-21 15:34:24 +01:00
Armin Schrenk 7ee0606306 adjust unit tests 2026-01-21 15:34:08 +01:00
Armin Schrenk 046372f95b refactored BufferedLog
* rename to EventualLogger
* adhere to slf4j API
* ensure single instance
2026-01-21 15:33:26 +01:00
Armin Schrenk c198adaf3f switch back to properties 2026-01-21 11:53:31 +01:00
Armin Schrenk d53f0880ca add test for AdminPropertiesSetter 2026-01-15 18:06:24 +01:00
Armin Schrenk 088b177c0e Ensure that null map is also logged 2026-01-15 15:11:46 +01:00
Armin Schrenk 287ab4e792 [skip ci] Update changelog 2026-01-15 15:11:12 +01:00
Armin SchrenkandGitHub 0e9cad5b09 Merge pull request #4103 from cryptomator/feature/basic-accessibility
Feature: Improve accessibility for core functionality
2026-01-15 10:44:16 +01:00
Armin Schrenk a0c9caeb21 [skip ci] update changelog 2026-01-14 17:57:24 +01:00
Armin Schrenk f620c6685a apply suggestions from AI review 2026-01-14 17:53:07 +01:00
Armin Schrenk 61be8c449c fixed flush does not clear BufferedLog 2026-01-14 17:39:49 +01:00
Armin Schrenk 43343b9954 fix wrong Linux path 2026-01-14 17:36:07 +01:00
Armin Schrenk 460b7e6225 [skip ci] update changelog 2026-01-14 17:33:45 +01:00
Armin Schrenk e2430bfb22 add null check 2026-01-14 17:29:56 +01:00
Armin Schrenk ac7c9c2165 use a bracket to "describe" the vault state 2026-01-14 17:28:20 +01:00
Jan-Peter Klein efd73e0d3e move recovery IO operations to background 2026-01-14 17:14:23 +01:00
Armin Schrenk b441803462 also adjust wix installer to new config format 2026-01-14 16:28:48 +01:00
Armin Schrenk 42b06aa556 Switch to JSON as config format
Java Properties require ISO 8859-1 character encoding, leading to manual edits of file.
2026-01-14 14:12:28 +01:00
Armin Schrenk b1c21501a6 Add dummy admin properties file in Windows installer 2026-01-13 18:40:53 +01:00
Armin Schrenk 45633837e0 only allow overwriting a subset of JVM properties 2026-01-13 17:26:48 +01:00
Armin Schrenk b23bd0b27a Implement logic to overwrite system properties set in app internal config file 2026-01-13 13:14:40 +01:00
Armin Schrenk b3f3faf4ee add DIALOG role to more dialogs 2026-01-13 11:02:01 +01:00
Armin Schrenk 33f26bf804 Refactor notificationbar
* rename to InfoBar
* replace closeButton text with graphic and add accessibilityText
* use common base class for styling and use CSS lookup for variants
2026-01-12 23:31:37 +01:00
Armin Schrenk a06accb80f add accessibletext to vault storage location 2026-01-12 23:15:40 +01:00
Armin Schrenk a50e372f05 add correct accessible role to dialogs 2026-01-12 23:14:09 +01:00
Armin Schrenk 06726303fb add proper accessibility text for vault list 2026-01-12 23:13:15 +01:00
Armin Schrenk 11c86f7287 impl idea 2026-01-12 11:59:17 +01:00
mindmonkandGitHub 8e68a62ab0 Merge pull request #4081 from cryptomator/feature/hub-vault-archived-dialog
Feature: Show dedicated “Archived Vault” screen on unlock when Hub returns 410
2026-01-06 11:20:29 +01:00
Jan-Peter Klein 787d0b8e12 code cleanup 2026-01-05 14:00:20 +01:00
Jan-Peter Klein ba765f7a69 code cleanup 2026-01-05 13:31:45 +01:00
Jan-Peter Klein e9d7e631c7 fix typo 2026-01-05 13:27:50 +01:00
Jan-Peter Klein 88acbc8ed7 fix typo 2026-01-05 13:22:01 +01:00
Jan-Peter Klein e84a73b9c3 use SimpleDialog 2026-01-05 13:17:10 +01:00
Jan-Peter Klein 2324ddad8b update changelog 2026-01-05 11:53:51 +01:00
Jan-Peter Klein 04da2504de Merge branch 'develop' into feature/hub-vault-archived-dialog 2026-01-05 11:28:08 +01:00
Jan-Peter Klein 760e260eba show archived vault dialog on unlock when Hub returns 410 2025-12-17 09:56:56 +01:00
Ralph Plawetzki 9a74194391 Make SecretServiceKeychainAccess the default selection 2025-10-27 05:33:35 +01:00
167 changed files with 2838 additions and 617 deletions
+2 -2
View File
@@ -48,7 +48,7 @@ runs:
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT" echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
shell: bash shell: bash
- name: Sign DLLs with Azure Trusted Signing - name: Sign DLLs with Azure Trusted Signing
uses: azure/trusted-signing-action@fc390cf8ed0f14e248a542af1d838388a47c7a7c # v0.5.10 uses: azure/artifact-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0
with: with:
files-folder: ${{ inputs.base-dir }} files-folder: ${{ inputs.base-dir }}
files-folder-filter: ${{ inputs.file-extensions }} files-folder-filter: ${{ inputs.file-extensions }}
@@ -59,7 +59,7 @@ runs:
azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }} azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }}
azure-client-id: ${{ steps.set-secrets.outputs.client-id }} azure-client-id: ${{ steps.set-secrets.outputs.client-id }}
azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }} azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }}
trusted-signing-account-name: cryptomatorSigning signing-account-name: cryptomatorSigning
certificate-profile-name: production certificate-profile-name: production
endpoint: https://weu.codesigning.azure.net/ endpoint: https://weu.codesigning.azure.net/
timestamp-rfc3161: http://timestamp.acs.microsoft.com timestamp-rfc3161: http://timestamp.acs.microsoft.com
+11 -11
View File
@@ -19,7 +19,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.0.LTS'
jobs: jobs:
get-version: get-version:
@@ -37,16 +37,16 @@ jobs:
include: include:
- os: ubuntu-latest - os: ubuntu-latest
appimage-suffix: x86_64 appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
- os: ubuntu-24.04-arm - os: ubuntu-24.04-arm
appimage-suffix: aarch64 appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4' openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -122,8 +122,8 @@ jobs:
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true" --java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
@@ -175,7 +175,7 @@ jobs:
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: appimage-${{ matrix.appimage-suffix }} name: appimage-${{ matrix.appimage-suffix }}
path: | path: |
@@ -201,7 +201,7 @@ jobs:
if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable' if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
steps: steps:
- name: Download AppImages - name: Download AppImages
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
path: downloads/ path: downloads/
merge-multiple: true merge-multiple: true
@@ -212,7 +212,7 @@ jobs:
echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT" echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1) AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT" echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'cryptomator/aur-bin' repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+1 -1
View File
@@ -48,7 +48,7 @@ jobs:
env: env:
AUR_PR_URL: tbd AUR_PR_URL: tbd
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'cryptomator/aur' repository: 'cryptomator/aur'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+3 -3
View File
@@ -51,7 +51,7 @@ jobs:
- name: Download file - name: Download file
run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: ${{ steps.extractName.outputs.fileName }} name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }} path: ${{ steps.extractName.outputs.fileName }}
@@ -63,7 +63,7 @@ jobs:
if: inputs.kaspersky if: inputs.kaspersky
steps: steps:
- name: Download artifact - name: Download artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
name: ${{ needs.download-file.outputs.fileName }} name: ${{ needs.download-file.outputs.fileName }}
path: upload path: upload
@@ -83,7 +83,7 @@ jobs:
if: inputs.avast if: inputs.avast
steps: steps:
- name: Download artifact - name: Download artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
name: ${{ needs.download-file.outputs.fileName }} name: ${{ needs.download-file.outputs.fileName }}
path: upload path: upload
+3 -3
View File
@@ -22,14 +22,14 @@ jobs:
name: Compile and Test name: Compile and Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
cache: 'maven' cache: 'maven'
- name: Cache SonarCloud packages - name: Cache SonarCloud packages
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with: with:
path: ~/.sonar/cache path: ~/.sonar/cache
key: ${{ runner.os }}-sonar key: ${{ runner.os }}-sonar
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV" run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
shell: pwsh shell: pwsh
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }} - name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
java-version: ${{ env.JDK_MAJOR_VERSION}} java-version: ${{ env.JDK_MAJOR_VERSION}}
distribution: ${{ env.JDK_VENDOR }} distribution: ${{ env.JDK_VENDOR }}
+8 -8
View File
@@ -23,12 +23,12 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.0.LTS'
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1' DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' OPENJFX_JMODS_AMD64_HASH: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip' OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4' OPENJFX_JMODS_AARCH64_HASH: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
jobs: jobs:
get-version: get-version:
@@ -43,7 +43,7 @@ jobs:
env: env:
INPUT_PPAVER: ${{ inputs.ppaver }} INPUT_PPAVER: ${{ inputs.ppaver }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- id: deb-version - id: deb-version
name: Determine deb-version name: Determine deb-version
run: | run: |
@@ -60,7 +60,7 @@ jobs:
env: env:
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }} DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -143,7 +143,7 @@ jobs:
run: | run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: linux-deb-package name: linux-deb-package
path: | path: |
+2 -2
View File
@@ -7,7 +7,7 @@ on:
jobs: jobs:
check-dependencies: check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@1074588008ae3326a2221ea451783280518f0366 # v3.0.1 uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # v3.0.3
with: with:
runner-os: 'ubuntu-latest' runner-os: 'ubuntu-latest'
java-distribution: 'temurin' java-distribution: 'temurin'
@@ -16,4 +16,4 @@ jobs:
nvd-api-key: ${{ secrets.NVD_API_KEY }} nvd-api-key: ${{ secrets.NVD_API_KEY }}
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }} ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }} ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }}
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
+1 -1
View File
@@ -53,7 +53,7 @@ jobs:
INTERVAL: 900 INTERVAL: 900
JSON_DATA: ${{ steps.get-stats.outputs.result }} JSON_DATA: ${{ steps.get-stats.outputs.result }}
- name: Upload Results - name: Upload Results
uses: fjogeleit/http-request-action@c0b95d02a088b47c1f2f4db04fd8af8bd19eee54 # v1.16.6 uses: fjogeleit/http-request-action@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0
with: with:
url: 'https://graphite-us-central1.grafana.net/metrics' url: 'https://graphite-us-central1.grafana.net/metrics'
method: 'POST' method: 'POST'
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
env: env:
FLATHUB_PR_URL: tbd FLATHUB_PR_URL: tbd
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'flathub/org.cryptomator.Cryptomator' repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+2 -2
View File
@@ -35,11 +35,11 @@ jobs:
revNum: ${{ steps.versions.outputs.revNum }} revNum: ${{ steps.versions.outputs.revNum }}
type: ${{ steps.versions.outputs.type}} type: ${{ steps.versions.outputs.type}}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
+7 -7
View File
@@ -24,7 +24,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.0.LTS'
jobs: jobs:
get-version: get-version:
@@ -44,12 +44,12 @@ jobs:
architecture: x64 architecture: x64
output-suffix: x64 output-suffix: x64
fuse-lib: macFUSE fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52' openjfx-sha: '0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -128,8 +128,8 @@ jobs:
--java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true" --java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\"" --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\"" --java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
@@ -283,7 +283,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true continue-on-error: true
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: dmg-${{ matrix.output-suffix }} name: dmg-${{ matrix.output-suffix }}
path: | path: |
+7 -7
View File
@@ -22,7 +22,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.0.LTS'
jobs: jobs:
get-version: get-version:
@@ -42,12 +42,12 @@ jobs:
architecture: aarch64 architecture: aarch64
output-suffix: arm64 output-suffix: arm64
fuse-lib: FUSE-T fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba' openjfx-sha: '4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -126,8 +126,8 @@ jobs:
--java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dapple.awt.enableTemplateImages=true"
--java-options "-Dsun.java2d.metal=true" --java-options "-Dsun.java2d.metal=true"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\"" --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\"" --java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
@@ -282,7 +282,7 @@ jobs:
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
continue-on-error: true continue-on-error: true
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: dmg-${{ matrix.output-suffix }} name: dmg-${{ matrix.output-suffix }}
path: | path: |
+2 -2
View File
@@ -16,8 +16,8 @@ jobs:
name: Compile and Test name: Compile and Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
+3 -3
View File
@@ -19,9 +19,9 @@ jobs:
name: Validate commits pushed to release/hotfix branch to fulfill release requirements name: Validate commits pushed to release/hotfix branch to fulfill release requirements
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -49,7 +49,7 @@ jobs:
exit 1 exit 1
fi fi
- name: Cache NVD DB - name: Cache NVD DB
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with: with:
path: ~/.m2/repository/org/owasp/dependency-check-data/ path: ~/.m2/repository/org/owasp/dependency-check-data/
key: dependency-check-${{ github.run_id }} key: dependency-check-${{ github.run_id }}
+25 -20
View File
@@ -22,11 +22,12 @@ on:
env: env:
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_windows-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7' OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi' WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a' WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe' WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
WIX_VERSION: '6.0.2'
defaults: defaults:
run: run:
@@ -51,9 +52,9 @@ jobs:
java-version: '25.0.1+8' java-version: '25.0.1+8'
java-package: 'jdk' java-package: 'jdk'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ matrix.java-dist }} distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
@@ -62,9 +63,11 @@ jobs:
cache: 'maven' cache: 'maven'
- name: Install wix and extensions - name: Install wix and extensions
run: | run: |
dotnet tool install --global wix --version 6.0.0 dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global wix.exe extension add --global WixToolset.UI.wixext/${WIX_VERSION}
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- name: Download and extract JavaFX jmods from Gluon - name: Download and extract JavaFX jmods from Gluon
if: matrix.arch == 'x64' if: matrix.arch == 'x64'
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip #In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
@@ -140,8 +143,8 @@ jobs:
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
--java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Dfile.encoding=\"utf-8\""
--java-options "-Djava.net.useSystemProxies=true" --java-options "-Djava.net.useSystemProxies=true"
--java-options "-Dcryptomator.adminConfigPath=\"C:/ProgramData/Cryptomator/config.properties\""
--java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\"" --java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\""
--java-options "-Dcryptomator.pluginDir=\"@{appdata}/Cryptomator/Plugins\""
--java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\"" --java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\""
--java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\"" --java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\""
@@ -200,7 +203,7 @@ jobs:
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign DLLs with Actalis CodeSigner - name: Sign DLLs with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release' if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'appdir' base-dir: 'appdir'
file-extensions: 'dll,exe,ps1' file-extensions: 'dll,exe,ps1'
@@ -277,7 +280,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: msi-${{ matrix.arch }} name: msi-${{ matrix.arch }}
path: | path: |
@@ -299,21 +302,23 @@ jobs:
java-version: '24.0.1+9' java-version: '24.0.1+9'
java-package: 'jdk' java-package: 'jdk'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install wix and extensions - name: Install wix and extensions
run: | run: |
dotnet tool install --global wix --version 6.0.0 dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global wix.exe extension add --global WixToolset.BootstrapperApplications.wixext/${WIX_VERSION}
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- name: Download .msi - name: Download .msi
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
name: msi-${{ matrix.arch }} name: msi-${{ matrix.arch }}
path: dist/win/bundle/resources path: dist/win/bundle/resources
- name: Strip version info from msi file name - name: Strip version info from msi file name
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ matrix.java-dist }} distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
@@ -376,7 +381,7 @@ jobs:
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign burn engine with Actalis CodeSigner - name: Sign burn engine with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release' if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'tmp' base-dir: 'tmp'
file-extensions: 'exe' file-extensions: 'exe'
@@ -400,7 +405,7 @@ jobs:
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
- name: Sign installer with Actalis CodeSigner - name: Sign installer with Actalis CodeSigner
if: inputs.sign || github.event_name == 'release' if: inputs.sign || github.event_name == 'release'
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'installer' base-dir: 'installer'
file-extensions: 'exe' file-extensions: 'exe'
@@ -418,7 +423,7 @@ jobs:
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: exe-${{ matrix.executable-suffix }} name: exe-${{ matrix.executable-suffix }}
path: | path: |
@@ -436,7 +441,7 @@ jobs:
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }} download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
steps: steps:
- name: Download installers - name: Download installers
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
merge-multiple: true merge-multiple: true
- name: Publish installers on GitHub Releases - name: Publish installers on GitHub Releases
+33 -10
View File
@@ -12,17 +12,15 @@
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" /> <outputRelativeToContentRoot value="true" />
<option name="dagger.fastInit" value="enabled" /> <option name="dagger.fastInit" value="enabled" />
<option name="dagger.formatGeneratedSource" value="enabled" />
<processorPath useClasspath="false"> <processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.57.2/dagger-compiler-2.57.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.57.2/dagger-2.57.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" /> <entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" /> <entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.57.2/dagger-spi-2.57.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.1.21-2.0.2/symbol-processing-api-2.1.21-2.0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" /> <entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
@@ -37,8 +35,33 @@
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" /> <entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" /> <entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" /> <entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.1.21/kotlin-metadata-jvm-2.1.21.jar" /> <entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.1.21/kotlin-stdlib-2.1.21.jar" /> <entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.41.0/checker-qual-3.41.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" /> <entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
</processorPath> </processorPath>
<module name="cryptomator" /> <module name="cryptomator" />
@@ -47,7 +70,7 @@
</component> </component>
<component name="JavacSettings"> <component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE"> <option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled" /> <module name="cryptomator" options="-Adagger.fastInit=enabled" />
</option> </option>
</component> </component>
</project> </project>
+31 -3
View File
@@ -15,8 +15,36 @@ Changes to prior versions can be found on the [Github release page](https://gith
* Implemented Flatpak update mechanism * Implemented Flatpak update mechanism
* App notifications ([#4069](https://github.com/cryptomator/cryptomator/pull/4069)) * App notifications ([#4069](https://github.com/cryptomator/cryptomator/pull/4069))
* Mark files in-use for Hub vaults ([#4078](https://github.com/cryptomator/cryptomator/pull/4078)) * Mark files in-use for Hub vaults ([#4078](https://github.com/cryptomator/cryptomator/pull/4078))
* Accessibility labels for GUI elements ([#4064](https://github.com/cryptomator/cryptomator/issues/4064), [#4066](https://github.com/cryptomator/cryptomator/pull/4066), [#4055](https://github.com/cryptomator/cryptomator/issues/4055)) * Accessibility: Adjust app to be used with a screen reader ([#547](https://github.com/cryptomator/cryptomator/issues/547))
* Show Archived Vault Dialog on unlock when Hub returns 410 ([#4081](https://github.com/cryptomator/cryptomator/pull/4081))
* Support automatic app theme selection according to OS theme on Linux ([#4027](https://github.com/cryptomator/cryptomator/issues/4027))
* Admin configuration: Allow overwriting certain app properties by external config file ([#4105](https://github.com/cryptomator/cryptomator/pull/4105))
* New keychain backend using [secret service API](https://specifications.freedesktop.org/secret-service/0.2) for Linux ([#4025](https://github.com/cryptomator/cryptomator/pull/4025))
### Fixed
* Fixed password reset/show recovery possible for vaults without masterkey file ([#4120](https://github.com/cryptomator/cryptomator/pull/4120))
* Fixed restore vault config failed due to selecting a directory instead of file ([#4141](https://github.com/cryptomator/cryptomator/issues/4141))
### Changed ### Changed
* Built using JDK 25 ([#4031](https://github.com/cryptomator/cryptomator/issues/4031)) * Disable user defined app start config on Windows ([#4132](https://github.com/cryptomator/cryptomator/issues/4132))
* Modernized Template for GitHub Releases * Disable plugin loading by default ([#4136](https://github.com/cryptomator/cryptomator/4136))
* Use JDK 25 ([#4031](https://github.com/cryptomator/cryptomator/pull/4031))
* Update JavaFX to 25.0.2 ([#4145](https://github.com/cryptomator/cryptomator/pull/4145)))
* Updated translations
* Updated dependencies
* `ch.qos.logback:*` from 1.5.19 to 1.5.31
* `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.0
* `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0
* `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
* `com.google.dagger:*` from 2.57.2 to 2.59.1
* `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0
* `org.cryptomator:cryptofs` from 2.9.0 to 2.10.0-beta3
* `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
* `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.0
* `org.cryptomator:integrations-api` from 1.7.0 to 1.8.0-beta1
* `org.cryptomator:integrations-linux` from 1.6.1 to 1.7.0-beta4
* `org.cryptomator:integrations-mac` from 1.4.1 to 1.5.0-beta3
* `org.cryptomator:integrations-win` from 1.5.1 to 1.6.0
* `org.cryptomator:webdav-nio-adapter` from 3.0.0 to 3.0.1
+1 -1
View File
@@ -78,7 +78,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies ### Dependencies
* JDK 24 (e.g. temurin, zulu) * JDK 25 (e.g. temurin, zulu)
* Maven 3 * Maven 3
### Run Maven ### Run Maven
+8
View File
@@ -0,0 +1,8 @@
# This is the Cryptomator administrative configuration file.
# It is a simple key-value pair file.
# Lines starting with '#' are comments and will be ignored.
# For more info, read the docs at https://docs.cryptomator.org/desktop/advanced-settings/
#
# Example:
# Sets the plugin directory and enables plugin loading
# cryptomator.pluginDir=@{userhome}/Cryptomator/Plugins
+4 -4
View File
@@ -23,12 +23,12 @@ mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
cp ../../../LICENSE.txt ../../../target cp ../../../LICENSE.txt ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=25 JAVAFX_VERSION=25.0.2
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' JAVAFX_JMODS_SHA256='e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
if [ "${CPU_ARCH}" = "aarch64" ]; then if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64" JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1' JAVAFX_JMODS_SHA256='c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
fi fi
# download javaFX jmods # download javaFX jmods
@@ -88,8 +88,8 @@ ${JAVA_HOME}/bin/jpackage \
--app-version "${VERSION}.${REVISION_NO}" \ --app-version "${VERSION}.${REVISION_NO}" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
--java-options "-Djava.net.useSystemProxies=true" \ --java-options "-Djava.net.useSystemProxies=true" \
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \ --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \ --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \ --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
+1 -1
View File
@@ -51,8 +51,8 @@ override_dh_auto_build:
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
--java-options "-Djava.net.useSystemProxies=true" \ --java-options "-Djava.net.useSystemProxies=true" \
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \ --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \ --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \ --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
+4 -4
View File
@@ -32,15 +32,15 @@ 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'` VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T" FUSE_LIB="FUSE-T"
JAVAFX_VERSION=25 JAVAFX_VERSION=25.0.2
JAVAFX_ARCH="undefined" JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined" JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64" JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba" JAVAFX_JMODS_SHA256="4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a"
else else
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52" JAVAFX_JMODS_SHA256="0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c"
fi fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip" JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
@@ -114,9 +114,9 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dapple.awt.enableTemplateImages=true" \ --java-options "-Dapple.awt.enableTemplateImages=true" \
--java-options "-Dsun.java2d.metal=true" \ --java-options "-Dsun.java2d.metal=true" \
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \ --java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" \
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \ --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \ --java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/${APP_NAME}/Plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/${APP_NAME}/settings.json\"" \ --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/${APP_NAME}/settings.json\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/${APP_NAME}/ipc.socket\"" \ --java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/${APP_NAME}/ipc.socket\"" \
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/${APP_NAME}/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/${APP_NAME}/key.p12\"" \
+7 -7
View File
@@ -34,20 +34,20 @@ if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
} }
if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null) if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null)
{ {
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.0)' Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.2)'
exit 1 exit 1
} }
$wixExtensions = & wix.exe extension list --global | Out-String $wixExtensions = & wix.exe extension list --global | Out-String
if ($wixExtensions -notmatch 'WixToolset.UI.wixext') { if ($wixExtensions -notmatch 'WixToolset.UI.wixext') {
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.0 --global)' Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.2 --global)'
exit 1 exit 1
} }
if ($wixExtensions -notmatch 'WixToolset.Util.wixext') { if ($wixExtensions -notmatch 'WixToolset.Util.wixext') {
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.0 --global)' Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.2 --global)'
exit 1 exit 1
} }
if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') { if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') {
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global)' Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.2 --global)'
exit 1 exit 1
} }
@@ -93,9 +93,9 @@ switch ($archName) {
$jmodPaths = "$Env:JAVA_HOME/jmods" $jmodPaths = "$Env:JAVA_HOME/jmods"
} }
'x64' { 'x64' {
$javaFxVersion='25' $javaFxVersion='25.0.2'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip" $javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7' $javaFxJmodsSHA256 = '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
$javaFxJmods = '.\resources\jfxJmods.zip' $javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) { if( !(Test-Path -Path $javaFxJmods) ) {
@@ -155,7 +155,7 @@ $javaOptions = @(
"--java-options", "-Djava.net.useSystemProxies=true" "--java-options", "-Djava.net.useSystemProxies=true"
"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" "--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`""
"--java-options", "-XX:ErrorFile=`"C:/cryptomator/cryptomator_crash.log`"" "--java-options", "-XX:ErrorFile=`"C:/cryptomator/cryptomator_crash.log`""
"--java-options", "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" "--java-options", "-Dcryptomator.adminConfigPath=`"C:/ProgramData/$AppName/config.properties`""
"--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" "--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`""
"--java-options", "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" "--java-options", "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`""
"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`"" "--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`""
+12
View File
@@ -0,0 +1,12 @@
@echo off
:: Batch wrapper for PowerShell script to disable user configuration in Cryptomator
:: This is executed as a Custom Action during MSI installation
:: This file must be located in the INSTALLDIR
:: Change to INSTALLDIR
cd %~dp0
:: Execute the PowerShell script
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File ".\disableUserConfig.ps1"
:: Return the exit code from PowerShell
exit /b %ERRORLEVEL%
+24
View File
@@ -0,0 +1,24 @@
# PowerShell script to disable user configuration
# This script is executed as a Custom Action during MSI installation
# It deletes the file .package, effectively disabling user specific jpackage configuration.
# NOTE: This file must be located in the same directory as set in the MSI property INSTALLDIR
try {
# Determine file path
$packageFile = Join-Path $PSScriptRoot 'app\.package'
#check if file exists
if (Test-Path -Path $packageFile) {
Write-Host "Deleting file: $packageFile"
Remove-Item -Path $packageFile -Force -ErrorAction Stop
} else {
Write-Host "File not found: $packageFile. Skipping deletion."
}
exit 0
}
catch {
Write-Error "Error deleting package file: $_"
exit 1
}
+29 -3
View File
@@ -87,7 +87,7 @@
<!-- Non-Opening ProgID --> <!-- Non-Opening ProgID -->
<ns0:DirectoryRef Id="INSTALLDIR"> <ns0:DirectoryRef Id="INSTALLDIR">
<ns0:Component Bitness="always64" Id="nonStartingProgID" > <ns0:Component Bitness="always64" Id="nonStartingProgID">
<ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/> <ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/>
<ns0:ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0"> <ns0:ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0">
<ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)"> <ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
@@ -99,6 +99,25 @@
</ns0:Component> </ns0:Component>
</ns0:DirectoryRef> </ns0:DirectoryRef>
<ns0:StandardDirectory Id="CommonAppDataFolder">
<ns0:Directory Id="CryptomatorDesktopProgramData" Name="Cryptomator">
<ns0:Component Id="AdminConfigDir" Guid="c078b7da-ba6e-4069-a5ab-5c0f0f9856a0">
<ns0:CreateFolder>
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
<util:PermissionEx User="Administrators" GenericAll="yes"/>
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
</ns0:CreateFolder>
</ns0:Component>
<ns0:Component Id="AdminConfigFile" NeverOverwrite="yes" Permanent="yes">
<ns0:File Id="EmptyAdminConfig" Source="$(env.JP_WIXWIZARD_RESOURCES)\..\..\common\cryptomator.config" Name="cryptomator.config" KeyPath="yes">
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
<util:PermissionEx User="Administrators" GenericAll="yes"/>
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
</ns0:File>
</ns0:Component>
</ns0:Directory>
</ns0:StandardDirectory>
<!-- Standard required root --> <!-- Standard required root -->
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1"> <ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
@@ -106,7 +125,9 @@
<ns0:ComponentGroupRef Id="Files"/> <ns0:ComponentGroupRef Id="Files"/>
<ns0:ComponentGroupRef Id="FileAssociations"/> <ns0:ComponentGroupRef Id="FileAssociations"/>
<!-- Ref to additional ProgIDs --> <!-- Ref to additional ProgIDs -->
<ns0:ComponentRef Id="nonStartingProgID" /> <ns0:ComponentRef Id="nonStartingProgID"/>
<ns0:ComponentRef Id="AdminConfigDir"/>
<ns0:ComponentRef Id="AdminConfigFile"/>
</ns0:Feature> </ns0:Feature>
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" /> <ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
@@ -132,6 +153,10 @@
<!-- Property for controlling update check behavior (can be set via command line) --> <!-- Property for controlling update check behavior (can be set via command line) -->
<ns0:Property Id="DISABLEUPDATECHECK" Secure="yes" /> <ns0:Property Id="DISABLEUPDATECHECK" Secure="yes" />
<!-- Disable user config -->
<ns0:SetProperty Id="DisableUserConfig" Value="&quot;[INSTALLDIR]disableUserConfig.bat&quot;" Sequence="execute" Before="DisableUserConfig" />
<ns0:CustomAction Id="DisableUserConfig" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- WebDAV patches --> <!-- WebDAV patches -->
<ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" Sequence="execute" Before="PatchWebDAV" /> <ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" Sequence="execute" Before="PatchWebDAV" />
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/> <ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
@@ -188,9 +213,10 @@
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" /> <ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" />
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* --> <ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
<ns0:Custom Action="DisableUserConfig" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<!-- Skip action on uninstall --> <!-- Skip action on uninstall -->
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file --> <!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
<ns0:Custom Action="PatchWebDAV" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/> <ns0:Custom Action="PatchWebDAV" After="DisableUserConfig" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
<!-- Configure update check setting if property is provided --> <!-- Configure update check setting if property is provided -->
<ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/> <ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
</ns0:InstallExecuteSequence> </ns0:InstallExecuteSequence>
+14 -13
View File
@@ -33,23 +33,25 @@
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds> <nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds>
<!-- cryptomator dependencies --> <!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.10.0-beta2</cryptomator.cryptofs.version> <cryptomator.cryptofs.version>2.10.0-beta3</cryptomator.cryptofs.version>
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
<cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version> <cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.5.1</cryptomator.integrations.win.version> <cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.5.0-beta3</cryptomator.integrations.mac.version> <cryptomator.integrations.mac.version>1.5.0-beta3</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.7.0-beta3</cryptomator.integrations.linux.version> <cryptomator.integrations.linux.version>1.7.0-beta4</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.1.0</cryptomator.fuse.version> <cryptomator.fuse.version>6.0.0</cryptomator.fuse.version>
<cryptomator.webdav.version>3.0.0</cryptomator.webdav.version> <cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
<!-- 3rd party dependencies --> <!-- 3rd party dependencies -->
<commons-lang3.version>3.19.0</commons-lang3.version> <caffeine.version>3.2.3</caffeine.version>
<dagger.version>2.57.2</dagger.version> <commons-lang3.version>3.20.0</commons-lang3.version>
<dagger.version>2.59.1</dagger.version>
<easybind.version>2.2</easybind.version> <easybind.version>2.2</easybind.version>
<jackson.version>2.20.0</jackson.version> <jackson.version>2.21.0</jackson.version>
<javafx.version>25</javafx.version> <javafx.version>25.0.2</javafx.version>
<jwt.version>4.5.0</jwt.version> <jwt.version>4.5.0</jwt.version>
<nimbus-jose.version>10.5</nimbus-jose.version> <nimbus-jose.version>10.5</nimbus-jose.version>
<logback.version>1.5.19</logback.version> <logback.version>1.5.31</logback.version>
<slf4j.version>2.0.17</slf4j.version> <slf4j.version>2.0.17</slf4j.version>
<tinyoauth2.version>0.8.1</tinyoauth2.version> <tinyoauth2.version>0.8.1</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version> <zxcvbn.version>1.9.0</zxcvbn.version>
@@ -94,7 +96,7 @@
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId> <artifactId>cryptolib</artifactId>
<version>2.2.1</version> <version>${cryptomator.cryptolib.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
@@ -228,7 +230,7 @@
<dependency> <dependency>
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
<version>3.2.2</version> <version>${caffeine.version}</version>
</dependency> </dependency>
<!-- JUnit / Mockito / Hamcrest --> <!-- JUnit / Mockito / Hamcrest -->
<dependency> <dependency>
@@ -330,7 +332,6 @@
</annotationProcessorPaths> </annotationProcessorPaths>
<compilerArgs> <compilerArgs>
<arg>-Adagger.fastInit=enabled</arg> <arg>-Adagger.fastInit=enabled</arg>
<arg>-Adagger.formatGeneratedSource=enabled</arg>
</compilerArgs> </compilerArgs>
</configuration> </configuration>
</plugin> </plugin>
+3
View File
@@ -14,11 +14,13 @@ import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider; import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider; import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
import org.cryptomator.integrations.tray.TrayMenuController; import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.logging.LogbackConfiguratorFactory; import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.networking.SSLContextProvider; import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.networking.SSLContextWithMacKeychain; import org.cryptomator.networking.SSLContextWithMacKeychain;
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore; import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
import org.cryptomator.networking.SSLContextWithWindowsCertStore; import org.cryptomator.networking.SSLContextWithWindowsCertStore;
import org.cryptomator.ui.fxapp.JfxUiAppearanceProvider;
import org.cryptomator.ui.traymenu.AwtTrayMenuController; import org.cryptomator.ui.traymenu.AwtTrayMenuController;
open module org.cryptomator.desktop { open module org.cryptomator.desktop {
@@ -61,6 +63,7 @@ open module org.cryptomator.desktop {
uses SSLContextProvider; uses SSLContextProvider;
uses org.cryptomator.event.NotificationHandler; uses org.cryptomator.event.NotificationHandler;
provides UiAppearanceProvider with JfxUiAppearanceProvider;
provides TrayMenuController with AwtTrayMenuController; provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory; provides Configurator with LogbackConfiguratorFactory;
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore; provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
@@ -61,6 +61,7 @@ public final class MasterkeyService {
Optional<Path> c9rFile = paths // Optional<Path> c9rFile = paths //
.filter(p -> p.toString().endsWith(".c9r")) // .filter(p -> p.toString().endsWith(".c9r")) //
.filter(p -> !p.endsWith("dir.c9r")) // .filter(p -> !p.endsWith("dir.c9r")) //
.filter(Files::isRegularFile) //
.findFirst(); .findFirst();
if (c9rFile.isEmpty()) { if (c9rFile.isEmpty()) {
LOG.info("Unable to detect Crypto scheme: No *.c9r file found in {}", vaultPath); LOG.info("Unable to detect Crypto scheme: No *.c9r file found in {}", vaultPath);
@@ -153,11 +153,6 @@ public class Settings {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void migrateLegacySettings(SettingsJson json) { private void migrateLegacySettings(SettingsJson json) {
// migrate renamed keychainAccess
if(this.keychainProvider.getValueSafe().equals("org.cryptomator.linux.keychain.SecretServiceKeychainAccess")) {
this.keychainProvider.setValue("org.cryptomator.linux.keychain.GnomeKeyringKeychainAccess");
}
// implicit migration of 1.6.x legacy setting "preferredVolumeImpl": // implicit migration of 1.6.x legacy setting "preferredVolumeImpl":
if (this.mountService.get() == null && json.preferredVolumeImpl != null) { if (this.mountService.get() == null && json.preferredVolumeImpl != null) {
this.mountService.set(switch (json.preferredVolumeImpl) { this.mountService.set(switch (json.preferredVolumeImpl) {
@@ -10,14 +10,6 @@ public enum UiTheme {
DARK("preferences.interface.theme.dark"), // DARK("preferences.interface.theme.dark"), //
AUTOMATIC("preferences.interface.theme.automatic"); AUTOMATIC("preferences.interface.theme.automatic");
public static UiTheme[] applicableValues() {
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) {
return values();
} else {
return new UiTheme[]{LIGHT, DARK};
}
}
private final String displayName; private final String displayName;
UiTheme(String displayName) { UiTheme(String displayName) {
@@ -0,0 +1,97 @@
package org.cryptomator.launcher;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.Reader;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Properties;
import java.util.Set;
/**
* Factory to generate admin properties.
*
* <p>
* Admin properties are {@link Properties} using system properties as defaults, but allow overwriting a specific set of properties with an external config file.
* Those properties are created by calling {@link #create()}. The method first reads system property {@value #ADMIN_PROP_FILE_KEY}. If it contains a path to a valid properties file, all overridable properties from the file are loaded into the returned admin properties.
* <p>
* The overridable properties are:
* <ul>
* <li>cryptomator.logDir</li>
* <li>cryptomator.pluginDir</li>
* <li>cryptomator.p12Path</li>
* <li>cryptomator.mountPointsDir</li>
* <li>cryptomator.disableUpdateCheck</li>
* </ul>
*
* @see Properties
* @see System#getProperties()
*/
class AdminPropertiesFactory {
private static final Logger LOG = EventualLogger.INSTANCE;
private static final long MAX_CONFIG_SIZE_BYTES = 8192;
private static final String ADMIN_PROP_FILE_KEY = "cryptomator.adminConfigPath";
private static final Set<String> ALLOWED_OVERRIDES = Set.of( //
"cryptomator.logDir", //
"cryptomator.pluginDir", //
"cryptomator.p12Path", //
"cryptomator.mountPointsDir", //
"cryptomator.disableUpdateCheck");
/**
* Creates new {@link Properties} containing overridable properties from the admin config.
* <p>
* The returned properties object uses as default the {@link System} properties.
* For a list of overridable properties, see {@link AdminPropertiesFactory}
*
* @return {@link Properties} containing overridable properties from the admin config and defaulting to system properties.
*/
static Properties create() {
var systemProps = System.getProperties();
var adminProps = new Properties(systemProps);
final String adminCfgPath = System.getProperty(ADMIN_PROP_FILE_KEY);
if (adminCfgPath == null) {
LOG.debug("Admin config property is not defined. Skipping.");
return adminProps;
}
var propsFromFile = loadPropertiesFromFile(Path.of(adminCfgPath));
for (var key : propsFromFile.stringPropertyNames()) {
if (ALLOWED_OVERRIDES.contains(key)) {
var value = propsFromFile.getProperty(key);
LOG.info("Overwriting {} with value {} from admin config.", key, value);
adminProps.setProperty(key, value);
} else {
LOG.debug("Property {} in admin config is not supported for override.", key);
}
}
return adminProps;
}
//visible for testing
static Properties loadPropertiesFromFile(Path adminPropertiesPath) {
var adminProps = new Properties();
try (FileChannel ch = FileChannel.open(adminPropertiesPath, StandardOpenOption.READ); //
Reader reader = Channels.newReader(ch, StandardCharsets.UTF_8)) {
if (ch.size() > MAX_CONFIG_SIZE_BYTES) {
throw new IOException("Config file %s exceeds maximum size of %d".formatted(adminPropertiesPath, MAX_CONFIG_SIZE_BYTES));
}
adminProps.load(reader);
} catch (NoSuchFileException _) {
//NO-OP
LOG.debug("No admin properties found at {}.", adminPropertiesPath);
} catch (IOException | IllegalArgumentException e) {
LOG.warn("Failed to read administrative properties from {}. Returning empty properties.", adminPropertiesPath, e);
}
return adminProps;
}
}
@@ -11,9 +11,9 @@ import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment; import org.cryptomator.common.Environment;
import org.cryptomator.common.ShutdownHook; import org.cryptomator.common.ShutdownHook;
import org.cryptomator.common.SubstitutingProperties; import org.cryptomator.common.SubstitutingProperties;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.ipc.IpcCommunicator; import org.cryptomator.ipc.IpcCommunicator;
import org.cryptomator.logging.DebugMode; import org.cryptomator.logging.DebugMode;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.ui.fxapp.FxApplicationComponent; import org.cryptomator.ui.fxapp.FxApplicationComponent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -35,7 +35,8 @@ public class Cryptomator {
private static final long STARTUP_TIME = System.currentTimeMillis(); private static final long STARTUP_TIME = System.currentTimeMillis();
static { static {
var lazyProcessedProps = new SubstitutingProperties(System.getProperties(), System.getenv()); var adminProps = AdminPropertiesFactory.create();
var lazyProcessedProps = new SubstitutingProperties(adminProps, System.getenv());
System.setProperties(lazyProcessedProps); System.setProperties(lazyProcessedProps);
CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME); CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
LOG = LoggerFactory.getLogger(Cryptomator.class); LOG = LoggerFactory.getLogger(Cryptomator.class);
@@ -64,6 +65,7 @@ public class Cryptomator {
} }
public static void main(String[] args) { public static void main(String[] args) {
EventualLogger.INSTANCE.drainTo(LOG);
var printVersion = Optional.ofNullable(args) // var printVersion = Optional.ofNullable(args) //
.stream() //Streams either one element (the args-array) or zero elements .stream() //Streams either one element (the args-array) or zero elements
.flatMap(Arrays::stream) // .flatMap(Arrays::stream) //
@@ -4,7 +4,6 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.cryptomator.integrations.autostart.AutoStartProvider; import org.cryptomator.integrations.autostart.AutoStartProvider;
import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.integrations.tray.TrayIntegrationProvider;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.fxapp.FxApplicationComponent; import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named; import javax.inject.Named;
@@ -30,11 +29,6 @@ class CryptomatorModule {
return new ArrayBlockingQueue<>(10); return new ArrayBlockingQueue<>(10);
} }
@Provides
@Singleton
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides @Provides
@Singleton @Singleton
@@ -0,0 +1,106 @@
package org.cryptomator.launcher;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.DefaultLoggingEvent;
import org.slf4j.event.Level;
import org.slf4j.event.LoggingEvent;
import org.slf4j.helpers.AbstractLogger;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
class EventualLogger extends AbstractLogger {
static final EventualLogger INSTANCE = new EventualLogger();
private final Queue<LoggingEvent> bufferedEvents = new ArrayDeque<>();
private EventualLogger() {
}
synchronized void drainTo(Logger gutter) {
for (var event : bufferedEvents) {
var builder = gutter.atLevel(event.getLevel()) //
.setCause(event.getThrowable()) //
.setMessage(event.getMessage());
Objects.requireNonNullElse(event.getArguments(), List.of()).forEach(builder::addArgument);
Objects.requireNonNullElse(event.getMarkers(), List.<Marker>of()).forEach(builder::addMarker);
builder.log();
}
bufferedEvents.clear();
}
@Override
protected synchronized void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, Throwable throwable) {
var event = new DefaultLoggingEvent(level, this);
if (marker != null) {
event.addMarker(marker);
}
event.setMessage(messagePattern);
for (var arg : Objects.requireNonNullElse(arguments, new Object[]{})) {
event.addArgument(arg);
}
event.setThrowable(throwable);
bufferedEvents.add(event);
}
//Unclear, unused and undocumented method of slf4j, see also https://github.com/qos-ch/slf4j/discussions/348
@Override
protected String getFullyQualifiedCallerName() {
return getClass().getCanonicalName();
}
@Override
public boolean isTraceEnabled() {
return true;
}
@Override
public boolean isTraceEnabled(Marker marker) {
return true;
}
@Override
public boolean isDebugEnabled() {
return true;
}
@Override
public boolean isDebugEnabled(Marker marker) {
return true;
}
@Override
public boolean isInfoEnabled() {
return true;
}
@Override
public boolean isInfoEnabled(Marker marker) {
return true;
}
@Override
public boolean isWarnEnabled() {
return true;
}
@Override
public boolean isWarnEnabled(Marker marker) {
return true;
}
@Override
public boolean isErrorEnabled() {
return true;
}
@Override
public boolean isErrorEnabled(Marker marker) {
return true;
}
}
@@ -59,7 +59,7 @@ public class ChooseExistingVaultController implements FxController {
this.vault = vault; this.vault = vault;
this.vaultListManager = vaultListManager; this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.screenshot = applicationStyle.appliedThemeProperty().map(this::selectScreenshot); this.screenshot = applicationStyle.appliedAppThemeProperty().map(this::selectScreenshot);
} }
private Image selectScreenshot(Theme theme) { private Image selectScreenshot(Theme theme) {
@@ -4,24 +4,27 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.AccessibleRole;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
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 javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import java.util.ResourceBundle;
public class NotificationBar extends HBox { public class InfoBar extends HBox {
@FXML @FXML
private Label notificationLabel; private Label infoMessage;
private final BooleanProperty dismissable = new SimpleBooleanProperty(); private final BooleanProperty dismissable = new SimpleBooleanProperty();
private final BooleanProperty notify = new SimpleBooleanProperty(); private final BooleanProperty notify = new SimpleBooleanProperty();
public NotificationBar() { public InfoBar() {
setAlignment(Pos.CENTER); setAlignment(Pos.CENTER);
setStyle("-fx-alignment: center;"); getStyleClass().addAll("info-bar");
Region spacer = new Region(); Region spacer = new Region();
spacer.setMinWidth(40); spacer.setMinWidth(40);
@@ -36,14 +39,21 @@ public class NotificationBar extends HBox {
vbox.setAlignment(Pos.CENTER); vbox.setAlignment(Pos.CENTER);
HBox.setHgrow(vbox, javafx.scene.layout.Priority.ALWAYS); HBox.setHgrow(vbox, javafx.scene.layout.Priority.ALWAYS);
notificationLabel = new Label(); infoMessage = new Label();
notificationLabel.getStyleClass().add("notification-label"); infoMessage.setFocusTraversable(true);
notificationLabel.setStyle("-fx-alignment: center;"); infoMessage.setAccessibleRole(AccessibleRole.BUTTON);
vbox.getChildren().add(notificationLabel); vbox.getChildren().add(infoMessage);
Button closeButton = new Button("X"); var closeGraphic = new FontAwesome5IconView();
closeGraphic.setGlyph(FontAwesome5Icon.TIMES);
closeGraphic.setGlyphSize(12);
closeGraphic.getStyleClass().add("glyph");
Button closeButton = new Button();
closeButton.setGraphic(closeGraphic);
closeButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
closeButton.setAccessibleText(ResourceBundle.getBundle("i18n.strings").getString("main.notification.closeButton.tooltip"));
closeButton.setMinWidth(40); closeButton.setMinWidth(40);
closeButton.setStyle("-fx-background-color: transparent; -fx-text-fill: white; -fx-font-weight: bold;");
closeButton.visibleProperty().bind(dismissable); closeButton.visibleProperty().bind(dismissable);
closeButton.setOnAction(_ -> { closeButton.setOnAction(_ -> {
@@ -61,11 +71,11 @@ public class NotificationBar extends HBox {
} }
public String getText() { public String getText() {
return notificationLabel.getText(); return infoMessage.getText();
} }
public void setText(String text) { public void setText(String text) {
notificationLabel.setText(text); infoMessage.setText(text);
} }
public void setStyleClass(String styleClass) { public void setStyleClass(String styleClass) {
@@ -61,6 +61,15 @@ public class Dialogs {
.setOkButtonKey(BUTTON_KEY_CLOSE); .setOkButtonKey(BUTTON_KEY_CLOSE);
} }
public SimpleDialog.Builder prepareHubVaultArchived(Stage window, Vault vault) {
return createDialogBuilder().setOwner(window) //
.setTitleKey("unlock.title", vault.getDisplayName()) //
.setMessageKey("hub.archived.message") //
.setDescriptionKey("hub.archived.description") //
.setIcon(FontAwesome5Icon.BAN)//
.setOkButtonKey(BUTTON_KEY_CLOSE);
}
public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window, String displayName) { public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window, String displayName) {
return createDialogBuilder().setOwner(window) // return createDialogBuilder().setOwner(window) //
.setTitleKey("recover.existing.title") // .setTitleKey("recover.existing.title") //
@@ -7,6 +7,7 @@ package org.cryptomator.ui.fxapp;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.decryptname.DecryptNameComponent; import org.cryptomator.ui.decryptname.DecryptNameComponent;
import org.cryptomator.ui.error.ErrorComponent; import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.eventview.EventViewComponent; import org.cryptomator.ui.eventview.EventViewComponent;
@@ -26,6 +27,7 @@ import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Optional;
@Module(subcomponents = {TrayMenuComponent.class, // @Module(subcomponents = {TrayMenuComponent.class, //
DecryptNameComponent.class, // DecryptNameComponent.class, //
@@ -41,7 +43,7 @@ import java.io.InputStream;
ShareVaultComponent.class, // ShareVaultComponent.class, //
EventViewComponent.class, // EventViewComponent.class, //
RecoveryKeyComponent.class, // RecoveryKeyComponent.class, //
NotificationComponent.class }) NotificationComponent.class})
abstract class FxApplicationModule { abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException { private static Image createImageFromResource(String resourceName) throws IOException {
@@ -50,6 +52,12 @@ abstract class FxApplicationModule {
} }
} }
@Provides
@FxApplicationScoped
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides @Provides
@FxApplicationScoped @FxApplicationScoped
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) { static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {
@@ -36,82 +36,91 @@ public class FxApplicationStyle {
} }
public void initialize() { public void initialize() {
var uiTheme = settings.theme.get();
if (uiTheme == UiTheme.AUTOMATIC) {
registerOsThemeListener();
}
applyTheme(uiTheme);
settings.theme.addListener(this::appThemeChanged); settings.theme.addListener(this::appThemeChanged);
loadSelectedStyleSheet(settings.theme.get());
} }
private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) { private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, UiTheme oldValue, UiTheme newValue) {
if (appearanceProvider.isPresent() && oldValue == UiTheme.AUTOMATIC && newValue != UiTheme.AUTOMATIC) { if (oldValue == newValue) {
// no-op
} else if (newValue == UiTheme.AUTOMATIC) {
registerOsThemeListener();
} else if (oldValue == UiTheme.AUTOMATIC) {
removeOsThemeListener();
}
applyTheme(newValue);
}
private void removeOsThemeListener() {
if (appearanceProvider.isPresent()) {
try { try {
appearanceProvider.get().removeListener(systemInterfaceThemeListener); appearanceProvider.get().removeListener(systemInterfaceThemeListener);
} catch (UiAppearanceException e) { } catch (UiAppearanceException e) {
LOG.error("Failed to disable automatic theme switching."); LOG.warn("Failed to disable automatic theme switching.", e);
}
}
loadSelectedStyleSheet(newValue);
}
private void loadSelectedStyleSheet(UiTheme desiredTheme) {
UiTheme theme = licenseHolder.isValidLicense() ? desiredTheme : UiTheme.LIGHT;
switch (theme) {
case LIGHT -> applyLightTheme();
case DARK -> applyDarkTheme();
case AUTOMATIC -> {
appearanceProvider.ifPresent(provider -> {
try {
provider.addListener(systemInterfaceThemeListener);
} catch (UiAppearanceException e) {
LOG.error("Failed to enable automatic theme switching.");
}
});
applySystemTheme();
} }
} else {
LOG.debug("Unable to remove listener os theme changes: No supported UiAppearanceProvider present");
} }
} }
private void systemInterfaceThemeChanged(Theme theme) { private void registerOsThemeListener() {
switch (theme) {
case LIGHT -> applyLightTheme();
case DARK -> applyDarkTheme();
}
}
private void applySystemTheme() {
if (appearanceProvider.isPresent()) { if (appearanceProvider.isPresent()) {
systemInterfaceThemeChanged(appearanceProvider.get().getSystemTheme()); try {
appearanceProvider.get().addListener(systemInterfaceThemeListener);
} catch (UiAppearanceException e) {
LOG.warn("Failed to enable automatic theme switching.", e);
}
} else { } else {
LOG.warn("No UiAppearanceProvider present, assuming LIGHT theme..."); LOG.warn("Unable to register for os theme changes: No supported UiAppearanceProvider present");
applyLightTheme();
} }
} }
private void applyLightTheme() { private void applyTheme(UiTheme uiTheme) {
var stylesheet = Optional // if (!licenseHolder.isValidLicense()) {
.ofNullable(getClass().getResource("/css/light_theme.bss")) // loadAndApplyLightTheme();
.orElse(getClass().getResource("/css/light_theme.css")); } else {
switch (uiTheme) {
case AUTOMATIC -> {
var osTheme = appearanceProvider.map(UiAppearanceProvider::getSystemTheme).orElse(Theme.LIGHT);
systemInterfaceThemeChanged(osTheme);
}
case LIGHT -> loadAndApplyLightTheme();
case DARK -> loadAndApplyDarkTheme();
}
}
}
private void systemInterfaceThemeChanged(Theme osTheme) {
switch (osTheme) {
case LIGHT -> loadAndApplyLightTheme();
case DARK -> loadAndApplyDarkTheme();
}
}
private void loadAndApplyLightTheme() {
loadAndApplyTheme(Theme.LIGHT, "/css/light_theme.css");
}
private void loadAndApplyDarkTheme() {
loadAndApplyTheme(Theme.DARK, "/css/dark_theme.css");
}
private void loadAndApplyTheme(Theme appTheme, String cssFile) {
var stylesheet = getClass().getResource(cssFile);
if (stylesheet == null) { if (stylesheet == null) {
LOG.warn("Failed to load light_theme stylesheet"); throw new IllegalStateException("Cannot find resource %s".formatted(cssFile));
} else {
Application.setUserAgentStylesheet(stylesheet.toString());
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(Theme.LIGHT));
appliedTheme.set(Theme.LIGHT);
} }
Application.setUserAgentStylesheet(stylesheet.toString());
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(appTheme));
appliedTheme.set(appTheme);
} }
private void applyDarkTheme() { public ObjectProperty<Theme> appliedAppThemeProperty() {
var stylesheet = Optional //
.ofNullable(getClass().getResource("/css/dark_theme.bss")) //
.orElse(getClass().getResource("/css/dark_theme.css"));
if (stylesheet == null) {
LOG.warn("Failed to load dark_theme stylesheet");
} else {
Application.setUserAgentStylesheet(stylesheet.toString());
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(Theme.DARK));
appliedTheme.set(Theme.DARK);
}
}
public ObjectProperty<Theme> appliedThemeProperty() {
return appliedTheme; return appliedTheme;
} }
} }
@@ -3,6 +3,8 @@ package org.cryptomator.ui.fxapp;
import org.cryptomator.event.FSEventBucket; import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent; import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator; import org.cryptomator.event.FileSystemEventAggregator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.application.Platform; import javafx.application.Platform;
@@ -11,6 +13,7 @@ import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import java.util.Map; import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -23,6 +26,8 @@ import java.util.concurrent.TimeUnit;
@FxApplicationScoped @FxApplicationScoped
public class FxFSEventList { public class FxFSEventList {
private static final Logger LOG = LoggerFactory.getLogger(FxFSEventList.class);
private final ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> events; private final ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> events;
private final FileSystemEventAggregator eventAggregator; private final FileSystemEventAggregator eventAggregator;
private final ScheduledExecutorService scheduler; private final ScheduledExecutorService scheduler;
@@ -37,7 +42,13 @@ public class FxFSEventList {
} }
public void schedulePollForUpdates() { public void schedulePollForUpdates() {
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS); try {
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS);
} catch ( RejectedExecutionException e) {
if(!scheduler.isShutdown()) {
LOG.warn("Failed to poll for filesystem events", e);
}
}
} }
/** /**
@@ -0,0 +1,68 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.integrations.common.DisplayName;
import org.cryptomator.integrations.common.OperatingSystem;
import org.cryptomator.integrations.common.Priority;
import org.cryptomator.integrations.uiappearance.Theme;
import org.cryptomator.integrations.uiappearance.UiAppearanceException;
import org.cryptomator.integrations.uiappearance.UiAppearanceListener;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.application.ColorScheme;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import java.util.concurrent.ConcurrentHashMap;
@DisplayName("JavaFX Color Scheme switcher")
@OperatingSystem(OperatingSystem.Value.LINUX)
@OperatingSystem(OperatingSystem.Value.WINDOWS)
@Priority(1050)
public class JfxUiAppearanceProvider implements UiAppearanceProvider {
private static final Logger LOG = LoggerFactory.getLogger(JfxUiAppearanceProvider.class);
private final ConcurrentHashMap<UiAppearanceListener, ChangeListener<ColorScheme>> uiAppearanceListeners = new ConcurrentHashMap<>();
private final Platform.Preferences preferences = Platform.getPreferences(); //Note: this service impl MUST be loaded in the fx application thread
@Override
public Theme getSystemTheme() {
return switch (preferences.getColorScheme()) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
}
@Override
public void adjustToTheme(Theme theme) {
//no-op
}
@Override
public void addListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var fxChangeListener = (ChangeListener<ColorScheme>) (_, _, newScheme) -> {
var newTheme = switch (newScheme) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
uiAppearanceListener.systemAppearanceChanged(newTheme);
};
LOG.debug("Register listener for OS theme changes");
uiAppearanceListeners.computeIfAbsent(uiAppearanceListener, k -> {
Platform.runLater(() -> preferences.colorSchemeProperty().addListener(fxChangeListener));
return fxChangeListener;
});
}
@Override
public void removeListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var fxChangeListener = uiAppearanceListeners.remove(uiAppearanceListener);
if (fxChangeListener != null) {
LOG.debug("Removing listener for OS theme changes");
Platform.runLater(() -> preferences.colorSchemeProperty().removeListener(fxChangeListener));
}
}
}
@@ -11,6 +11,7 @@ import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.dialogs.Dialogs;
import org.cryptomator.ui.keyloading.KeyLoading; import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -58,6 +59,8 @@ public class ReceiveKeyController implements FxController {
private final Lazy<Scene> accountInitializationScene; private final Lazy<Scene> accountInitializationScene;
private final Lazy<Scene> invalidLicenseScene; private final Lazy<Scene> invalidLicenseScene;
private final HttpClient httpClient; private final HttpClient httpClient;
private final Dialogs dialogs;
private final Vault vault;
@Inject @Inject
public ReceiveKeyController(@KeyLoading Vault vault, // public ReceiveKeyController(@KeyLoading Vault vault, //
@@ -72,7 +75,8 @@ public class ReceiveKeyController implements FxController {
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, // @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, //
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, // @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, //
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, // @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, //
@FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene) { @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene, //
Dialogs dialogs) {
this.window = window; this.window = window;
this.hubConfig = hubConfig; this.hubConfig = hubConfig;
this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs) this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs)
@@ -87,6 +91,8 @@ public class ReceiveKeyController implements FxController {
this.invalidLicenseScene = invalidLicenseScene; this.invalidLicenseScene = invalidLicenseScene;
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed); this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build(); this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build();
this.dialogs = dialogs;
this.vault = vault;
} }
@FXML @FXML
@@ -226,7 +232,8 @@ public class ReceiveKeyController implements FxController {
switch (response.statusCode()) { switch (response.statusCode()) {
case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey); case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey);
case 402 -> licenseExceeded(); case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access - TODO: add specific dialog? case 403 -> accessNotGranted();
case 410 -> accessGoneVaultArchived();
case 449 -> accountInitializationRequired(); case 449 -> accountInitializationRequired();
default -> throw new IllegalStateException("Unexpected response " + response.statusCode()); default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
} }
@@ -270,7 +277,8 @@ public class ReceiveKeyController implements FxController {
switch (response.statusCode()) { switch (response.statusCode()) {
case 200 -> receivedLegacyAccessTokenSuccess(response.body()); case 200 -> receivedLegacyAccessTokenSuccess(response.body());
case 402 -> licenseExceeded(); case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access case 403 -> accessNotGranted();
case 410 -> accessGoneVaultArchived();
case 404 -> needsLegacyDeviceRegistration(); case 404 -> needsLegacyDeviceRegistration();
default -> throw new IOException("Unexpected response " + response.statusCode()); default -> throw new IOException("Unexpected response " + response.statusCode());
} }
@@ -303,6 +311,11 @@ public class ReceiveKeyController implements FxController {
window.setScene(unauthorizedScene.get()); window.setScene(unauthorizedScene.get());
} }
private void accessGoneVaultArchived() {
window.close();
dialogs.prepareHubVaultArchived((Stage)window.getOwner(), vault).build().showAndWait();
}
private void accountInitializationRequired() { private void accountInitializationRequired() {
window.setScene(accountInitializationScene.get()); window.setScene(accountInitializationScene.get());
} }
@@ -16,6 +16,7 @@ import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import java.util.ResourceBundle;
// unscoped because each cell needs its own controller // unscoped because each cell needs its own controller
public class VaultListCellController implements FxController { public class VaultListCellController implements FxController {
@@ -23,9 +24,12 @@ public class VaultListCellController implements FxController {
private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12); private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12);
private static final Insets DEFAULT_INSETS = new Insets(12); private static final Insets DEFAULT_INSETS = new Insets(12);
private final ResourceBundle resourceBundle;
private final ObjectProperty<Vault> vault = new SimpleObjectProperty<>(); private final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
private final ObservableValue<VaultState.Value> vaultState;
private final ObservableValue<FontAwesome5Icon> glyph; private final ObservableValue<FontAwesome5Icon> glyph;
private final ObservableValue<Boolean> compactMode; private final ObservableValue<Boolean> compactMode;
private final ObservableValue<String> accessibleText;
private AutoAnimator spinAnimation; private AutoAnimator spinAnimation;
@@ -35,17 +39,21 @@ public class VaultListCellController implements FxController {
public HBox vaultListCell; public HBox vaultListCell;
@Inject @Inject
VaultListCellController(Settings settings) { VaultListCellController(Settings settings, ResourceBundle resourceBundle) {
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState); this.resourceBundle = resourceBundle;
this.vaultState = vault.flatMap(Vault::stateProperty);
this.glyph = vaultState.map(this::getGlyphForVaultState);
this.accessibleText = vaultState.map(this::getAccessibleTextForVaultState);
this.compactMode = settings.compactMode; this.compactMode = settings.compactMode;
} }
public void initialize() { public void initialize() {
this.spinAnimation = AutoAnimator.animate(Animations.createDiscrete360Rotation(vaultStateView)) // this.spinAnimation = AutoAnimator.animate(Animations.createDiscrete360Rotation(vaultStateView)) //
.onCondition(vault.flatMap(Vault::stateProperty).map(VaultState.Value.PROCESSING::equals).orElse(false)) // .onCondition(vaultState.map(VaultState.Value.PROCESSING::equals).orElse(false)) //
.afterStop(() -> vaultStateView.setRotate(0)) // .afterStop(() -> vaultStateView.setRotate(0)) //
.build(); .build();
this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS)); this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS));
this.vaultListCell.accessibleTextProperty().bind(accessibleText);
} }
// TODO deduplicate w/ VaultDetailController // TODO deduplicate w/ VaultDetailController
@@ -62,6 +70,25 @@ public class VaultListCellController implements FxController {
} }
} }
private String getAccessibleTextForVaultState(VaultState.Value state) {
var v = vault.get();
if (state != null && v != null) {
var translationKey = switch (state) {
case LOCKED -> "vault.state.locked";
case PROCESSING -> "vault.state.processing";
case UNLOCKED -> "vault.state.unlocked";
case NEEDS_MIGRATION -> "vault.state.migrationNeeded";
case MISSING -> "vault.state.missing";
case VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> "vault.state.error";
};
var localizedState = resourceBundle.getString(translationKey);
return resourceBundle.getString("main.vaultlist.listEntry").formatted(v.getDisplayName(), localizedState);
} else {
return "";
}
}
/* Getter/Setter */ /* Getter/Setter */
public ObservableValue<FontAwesome5Icon> glyphProperty() { public ObservableValue<FontAwesome5Icon> glyphProperty() {
@@ -101,15 +101,10 @@ public class NotificationController implements FxController {
var device = userAndDevice.length == 1 ? userAndDevice[0] : userAndDevice[1]; var device = userAndDevice.length == 1 ? userAndDevice[0] : userAndDevice[1];
var cleartextFileName = fiiue.cleartextPath().substring(fiiue.cleartextPath().lastIndexOf('/') + 1); var cleartextFileName = fiiue.cleartextPath().substring(fiiue.cleartextPath().lastIndexOf('/') + 1);
eventTimestamp.set(localizedTimeFormatter.format(fiiue.lastUpdated())); eventTimestamp.set(localizedTimeFormatter.format(fiiue.lastUpdated()));
message.set("File is locked by another device");
fileName.set(cleartextFileName);
description.set("The file is opened by %s on device %s. Ask the user to close the file and sync again. Otherwise, you can ignore the lock and open it anyway.".formatted(user, device));
actionText.set("Ignore Lock");
/* TODO: Once feature is out of beta, activate translations
message.set(resourceBundle.getString("notification.inUse.message")); message.set(resourceBundle.getString("notification.inUse.message"));
description.set(resourceBundle.getString("notification.inUse.description").formatted(fiiue.cleartextPath(), user, device)); fileName.set(cleartextFileName);
description.set(resourceBundle.getString("notification.inUse.description").formatted(user, device));
actionText.set(resourceBundle.getString("notification.inUse.action")); actionText.set(resourceBundle.getString("notification.inUse.action"));
*/
} }
default -> { default -> {
message.set("NO CONTENT"); message.set("NO CONTENT");
@@ -101,8 +101,9 @@ public class GeneralPreferencesController implements FxController {
} }
private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) { private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) {
//currently, we only migrate on macOS (touchID vs regular keychain) //currently, we migrate on macOS (touchID vs regular keychain)
if (SystemUtils.IS_OS_MAC) { //and on Linux (GNOME Keyring / KDE Wallet / Secret Service)
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_LINUX) {
var idsAndNames = settings.directories.stream().collect(Collectors.toMap(vs -> vs.id, vs -> vs.displayName.getValue())); var idsAndNames = settings.directories.stream().collect(Collectors.toMap(vs -> vs.id, vs -> vs.displayName.getValue()));
if (!idsAndNames.isEmpty()) { if (!idsAndNames.isEmpty()) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
@@ -56,7 +56,7 @@ public class InterfacePreferencesController implements FxController {
@FXML @FXML
public void initialize() { public void initialize() {
themeChoiceBox.getItems().addAll(UiTheme.applicableValues()); themeChoiceBox.getItems().addAll(UiTheme.values());
if (!themeChoiceBox.getItems().contains(settings.theme.get())) { if (!themeChoiceBox.getItems().contains(settings.theme.get())) {
settings.theme.set(UiTheme.LIGHT); settings.theme.set(UiTheme.LIGHT);
} }
@@ -104,7 +104,7 @@ public class RecoveryKeyCreationController implements FxController {
descriptionLabel.formatProperty().set(resourceBundle.getString("recoveryKey.recover.description")); descriptionLabel.formatProperty().set(resourceBundle.getString("recoveryKey.recover.description"));
cancelButton.setOnAction((_) -> back()); cancelButton.setOnAction((_) -> back());
cancelButton.setText(resourceBundle.getString("generic.button.back")); cancelButton.setText(resourceBundle.getString("generic.button.back"));
nextButton.setOnAction((_) -> restoreWithPassword()); nextButton.setOnAction((_) -> restoreWithPasswordAsync());
} }
} }
@@ -137,11 +137,47 @@ public class RecoveryKeyCreationController implements FxController {
} }
@FXML @FXML
public void restoreWithPassword() { public void restoreWithPasswordAsync() {
Task<Void> task = RecoveryKeyTasks.createTask(this::restoreWithPassword);
task.setOnScheduled(_ -> {
LOG.debug("Restoring vault configuration with password for {}.", vault.getDisplayablePath());
});
task.setOnSucceeded(_ -> {
LOG.debug("Restored vault configuration for {}.", vault.getDisplayablePath());
try {
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
vaultListManager.add(vault.getPath());
}
window.close();
dialogs.prepareRecoverPasswordSuccess((Stage) window.getOwner()) //
.setTitleKey("recover.recoverVaultConfig.title") //
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
.setDescriptionKey("recoveryKey.recover.resetMasterkeyFileSuccess.description")
.build().showAndWait();
} catch (IOException e) {
LOG.error("Failed to add vault to list.", e);
appWindows.showErrorWindow(e, window, null);
}
});
task.setOnFailed(_ -> {
if (task.getException() instanceof InvalidPassphraseException e) {
LOG.info("Password invalid", e);
Animations.createShakeWindowAnimation(window).play();
} else {
LOG.error("Recovery process failed.", task.getException());
appWindows.showErrorWindow(task.getException(), window, null);
}
});
executor.submit(task);
}
void restoreWithPassword() throws IOException, CryptoException {
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) { try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
Path recoveryPath = recoveryDirectory.getRecoveryPath(); Path recoveryPath = recoveryDirectory.getRecoveryPath();
Path masterkeyFilePath = vault.getPath().resolve(MASTERKEY_FILENAME); Path masterkeyFilePath = vault.getPath().resolve(MASTERKEY_FILENAME);
try (Masterkey masterkey = MasterkeyService.load(masterkeyFileAccess, masterkeyFilePath, passwordField.getCharacters())) { try (Masterkey masterkey = MasterkeyService.load(masterkeyFileAccess, masterkeyFilePath, passwordField.getCharacters())) {
@@ -152,23 +188,6 @@ public class RecoveryKeyCreationController implements FxController {
} }
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME); recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
vaultListManager.add(vault.getPath());
}
window.close();
dialogs.prepareRecoverPasswordSuccess((Stage)window.getOwner()) //
.setTitleKey("recover.recoverVaultConfig.title") //
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
.setDescriptionKey("recoveryKey.recover.resetMasterkeyFileSuccess.description")
.build().showAndWait();
} catch (InvalidPassphraseException e) {
LOG.info("Password invalid", e);
Animations.createShakeWindowAnimation(window).play();
} catch (IOException | CryptoException | IllegalStateException e) {
LOG.error("Recovery process failed", e);
appWindows.showErrorWindow(e, window, null);
} }
} }
@@ -117,14 +117,46 @@ public class RecoveryKeyResetPasswordController implements FxController {
@FXML @FXML
public void next() { public void next() {
switch (recoverType.get()) { switch (recoverType.get()) {
case RESTORE_ALL -> restorePassword(); case RESTORE_ALL -> restorePasswordAsync();
case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword(); case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword();
default -> resetPassword(); // Fallback default -> resetPassword(); // Fallback
} }
} }
@FXML @FXML
public void restorePassword() { public void restorePasswordAsync() {
Task<Void> task = RecoveryKeyTasks.createTask(this::restorePassword);
task.setOnScheduled(_ -> {
LOG.debug("Restoring vault configuration for {}.", vault.getDisplayablePath());
});
task.setOnSucceeded(_ -> {
LOG.debug("Restored vault configuration for {}.", vault.getDisplayablePath());
try {
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
vaultListManager.add(vault.getPath());
}
window.close();
dialogs.prepareRecoverPasswordSuccess((Stage) window.getOwner()) //
.setTitleKey("recover.recoverVaultConfig.title") //
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
.build().showAndWait();
} catch (IOException e) {
LOG.error("Failed to add vault to list.", e);
appWindows.showErrorWindow(e, window, null);
}
});
task.setOnFailed(_ -> {
LOG.error("Recovery process failed.", task.getException());
appWindows.showErrorWindow(task.getException(), window, null);
});
executor.submit(task);
}
void restorePassword() throws IOException, CryptoException {
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) { try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
Path recoveryPath = recoveryDirectory.getRecoveryPath(); Path recoveryPath = recoveryDirectory.getRecoveryPath();
MasterkeyService.recoverFromRecoveryKey(recoveryKey.get(), recoveryKeyFactory, recoveryPath, newPasswordController.passwordField.getCharacters()); MasterkeyService.recoverFromRecoveryKey(recoveryKey.get(), recoveryKeyFactory, recoveryPath, newPasswordController.passwordField.getCharacters());
@@ -135,19 +167,6 @@ public class RecoveryKeyResetPasswordController implements FxController {
recoveryDirectory.moveRecoveredFile(MASTERKEY_FILENAME); recoveryDirectory.moveRecoveredFile(MASTERKEY_FILENAME);
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME); recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
vaultListManager.add(vault.getPath());
}
window.close();
dialogs.prepareRecoverPasswordSuccess((Stage)window.getOwner()) //
.setTitleKey("recover.recoverVaultConfig.title") //
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
.build().showAndWait();
} catch (IOException | CryptoException e) {
LOG.error("Recovery process failed", e);
appWindows.showErrorWindow(e, window, null);
} }
} }
@@ -0,0 +1,25 @@
package org.cryptomator.ui.recoverykey;
import javafx.concurrent.Task;
final class RecoveryKeyTasks {
private RecoveryKeyTasks() {
}
@FunctionalInterface
interface TaskAction {
void run() throws Exception;
}
static Task<Void> createTask(TaskAction action) {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
action.run();
return null;
}
};
}
}
@@ -9,11 +9,15 @@ import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent; import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.nio.file.Files;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
@VaultOptionsScoped @VaultOptionsScoped
public class MasterkeyOptionsController implements FxController { public class MasterkeyOptionsController implements FxController {
@@ -25,6 +29,7 @@ public class MasterkeyOptionsController implements FxController {
private final ForgetPasswordComponent.Builder forgetPasswordWindow; private final ForgetPasswordComponent.Builder forgetPasswordWindow;
private final KeychainManager keychain; private final KeychainManager keychain;
private final ObservableValue<Boolean> passwordSaved; private final ObservableValue<Boolean> passwordSaved;
private final BooleanProperty masterkeyFileAvailable;
@Inject @Inject
@@ -40,6 +45,7 @@ public class MasterkeyOptionsController implements FxController {
} else { } else {
this.passwordSaved = new SimpleBooleanProperty(false); this.passwordSaved = new SimpleBooleanProperty(false);
} }
this.masterkeyFileAvailable = new SimpleBooleanProperty(Files.exists(vault.getPath().resolve(MASTERKEY_FILENAME)));
} }
@FXML @FXML
@@ -70,4 +76,12 @@ public class MasterkeyOptionsController implements FxController {
public boolean isPasswordSaved() { public boolean isPasswordSaved() {
return passwordSaved.getValue(); return passwordSaved.getValue();
} }
public BooleanProperty masterkeyFileAvailableProperty() {
return masterkeyFileAvailable;
}
public boolean isMasterkeyFileAvailable() {
return masterkeyFileAvailable.get();
}
} }
+45 -19
View File
@@ -50,6 +50,7 @@
GREEN_5: PRIMARY; GREEN_5: PRIMARY;
RED_5: #E74C3C; RED_5: #E74C3C;
ORANGE_5: #E67E22; ORANGE_5: #E67E22;
YELLOW_4: #C19F0E;
YELLOW_5: #F1C40F; YELLOW_5: #F1C40F;
MAIN_BG: GRAY_1; MAIN_BG: GRAY_1;
@@ -387,37 +388,62 @@
/******************************************************************************* /*******************************************************************************
* * * *
* NotificationBar * * InfoBar *
* * * *
******************************************************************************/ ******************************************************************************/
.info-bar {
-fx-alignment: center;
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: -bar-bg;
}
.notification-label { .info-bar--green {
-fx-text-fill: white; -bar-bg: GREEN_5;
-button-bg: GREEN_5;
-button-bg-pressed: GREEN_3;
}
.info-bar--yellow {
-bar-bg: YELLOW_5;
-button-bg: YELLOW_5;
-button-bg-pressed: YELLOW_4;
}
.info-bar--red {
-bar-bg: RED_5;
-button-bg: RED_5;
-button-bg-pressed: RED_5;
}
.info-bar .label {
-fx-text-fill: GRAY_9;
-fx-font-weight: bold; -fx-font-weight: bold;
} }
.notification-debug { .info-bar--yellow .label {
-fx-min-height:24px; -fx-text-fill: GRAY_9;
-fx-max-height:24px; -fx-font-weight: bold;
-fx-background-color: RED_5; -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
} }
.notification-update { .info-bar .glyph {
-fx-min-height:24px; -fx-fill: GRAY_9;
-fx-max-height:24px;
-fx-background-color: YELLOW_5;
} }
.notification-support { .info-bar:hover .label {
-fx-min-height:24px; -fx-underline:true;
-fx-max-height:24px;
-fx-background-color: PRIMARY;
} }
.notification-debug:hover .notification-label, .info-bar .button {
.notification-update:hover .notification-label, -fx-background-color: transparent;
.notification-support:hover .notification-label { -fx-border-color: transparent;
-fx-underline:true; -fx-padding: 2 2 2 2;
}
.info-bar .button:armed {
-fx-background-color: -button-bg-pressed;
-fx-background-radius: 8;
} }
/******************************************************************************* /*******************************************************************************
+46 -20
View File
@@ -50,6 +50,7 @@
GREEN_5: PRIMARY; GREEN_5: PRIMARY;
RED_5: #E74C3C; RED_5: #E74C3C;
ORANGE_5: #E67E22; ORANGE_5: #E67E22;
YELLOW_4: #C19F0E;
YELLOW_5: #F1C40F; YELLOW_5: #F1C40F;
MAIN_BG: GRAY_9; MAIN_BG: GRAY_9;
@@ -387,39 +388,64 @@
/******************************************************************************* /*******************************************************************************
* * * *
* NotificationBar * * InfoBar *
* * * *
******************************************************************************/ ******************************************************************************/
.info-bar {
-fx-alignment: center;
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: -bar-bg;
}
.notification-label { .info-bar--green {
-fx-text-fill: white; -bar-bg: GREEN_5;
-button-bg: GREEN_5;
-button-bg-pressed: GREEN_3;
}
.info-bar--yellow {
-bar-bg: YELLOW_5;
-button-bg: YELLOW_5;
-button-bg-pressed: YELLOW_4;
}
.info-bar--red {
-bar-bg: RED_5;
-button-bg: RED_5;
-button-bg-pressed: RED_5;
}
.info-bar .label {
-fx-text-fill: GRAY_9;
-fx-font-weight: bold; -fx-font-weight: bold;
} }
.notification-debug { .info-bar--yellow .label {
-fx-min-height:24px; -fx-text-fill: GRAY_9;
-fx-max-height:24px; -fx-font-weight: bold;
-fx-background-color: RED_5; -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
} }
.notification-update { .info-bar .glyph {
-fx-min-height:24px; -fx-fill: GRAY_9;
-fx-max-height:24px;
-fx-background-color: YELLOW_5;
} }
.notification-support { .info-bar:hover .label {
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: PRIMARY;
}
.notification-debug:hover .notification-label,
.notification-update:hover .notification-label,
.notification-support:hover .notification-label {
-fx-underline:true; -fx-underline:true;
} }
.info-bar .button {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-padding: 2 2 2 2;
}
.info-bar .button:armed {
-fx-background-color: -button-bg-pressed;
-fx-background-radius: 8;
}
/******************************************************************************* /*******************************************************************************
* * * *
* ScrollBar * * ScrollBar *
@@ -13,7 +13,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="24" spacing="24"
alignment="CENTER"> alignment="CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
@@ -19,7 +19,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="CENTER_LEFT"> alignment="CENTER_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
@@ -19,7 +19,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="CENTER_LEFT"> alignment="CENTER_LEFT"
accessibleRole="DIALOG">
<fx:define> <fx:define>
<ToggleGroup fx:id="locationPresetsToggler"/> <ToggleGroup fx:id="locationPresetsToggler"/>
<FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES"/> <FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES"/>
@@ -17,7 +17,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="CENTER_LEFT"> alignment="CENTER_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
@@ -15,7 +15,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="CENTER_LEFT"> alignment="CENTER_LEFT"
accessibleRole="DIALOG">
<fx:define> <fx:define>
<ToggleGroup fx:id="recoveryKeyChoice"/> <ToggleGroup fx:id="recoveryKeyChoice"/>
</fx:define> </fx:define>
@@ -11,7 +11,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="CENTER_LEFT"> alignment="CENTER_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
@@ -16,7 +16,8 @@
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
+2 -1
View File
@@ -13,7 +13,8 @@
fx:controller="org.cryptomator.ui.changepassword.ChangePasswordController" fx:controller="org.cryptomator.ui.changepassword.ChangePasswordController"
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -15,7 +15,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -19,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -22,7 +22,8 @@
minHeight="450" minHeight="450"
prefWidth="450" prefWidth="450"
prefHeight="450" prefHeight="450"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="24"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
+2 -1
View File
@@ -21,7 +21,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -20,7 +20,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -20,7 +20,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -20,7 +20,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -11,6 +11,7 @@
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?> <?import javafx.scene.shape.Circle?>
<!-- TODO: simple dialog -->
<HBox xmlns:fx="http://javafx.com/fxml" <HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.RegisterFailedController" fx:controller="org.cryptomator.ui.keyloading.hub.RegisterFailedController"
@@ -18,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -21,7 +21,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -19,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -19,7 +19,8 @@
maxWidth="500" maxWidth="500"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+7 -7
View File
@@ -3,7 +3,7 @@
<?import javafx.scene.control.SplitPane?> <?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import org.cryptomator.ui.controls.NotificationBar?> <?import org.cryptomator.ui.controls.InfoBar?>
<StackPane xmlns:fx="http://javafx.com/fxml" <StackPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
@@ -11,23 +11,23 @@
fx:controller="org.cryptomator.ui.mainwindow.MainWindowController" fx:controller="org.cryptomator.ui.mainwindow.MainWindowController"
styleClass="main-window"> styleClass="main-window">
<VBox minWidth="600"> <VBox minWidth="600">
<NotificationBar onMouseClicked="#showUpdatePreferences" <InfoBar onMouseClicked="#showUpdatePreferences"
text="%main.notification.updateAvailable" text="%main.notification.updateAvailable"
dismissable="true" dismissable="true"
notify="${controller.updateAvailable}" notify="${controller.updateAvailable}"
styleClass="notification-update"/> styleClass="info-bar--yellow"/>
<NotificationBar onMouseClicked="#showContributePreferences" <InfoBar onMouseClicked="#showContributePreferences"
text="%main.notification.support" text="%main.notification.support"
dismissable="true" dismissable="true"
notify="${!controller.licenseValid}" notify="${!controller.licenseValid}"
styleClass="notification-support"/> styleClass="info-bar--green"/>
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS"> <SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS">
<fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/> <fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/>
<fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/> <fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/>
</SplitPane> </SplitPane>
<NotificationBar onMouseClicked="#showGeneralPreferences" <InfoBar onMouseClicked="#showGeneralPreferences"
text="DEBUG MODE" text="DEBUG MODE"
styleClass="notification-debug" styleClass="info-bar--red"
notify="${controller.debugModeEnabled}"/> notify="${controller.debugModeEnabled}"/>
</VBox> </VBox>
</StackPane> </StackPane>
@@ -16,7 +16,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -19,7 +19,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -20,7 +20,8 @@
fx:controller="org.cryptomator.ui.migration.MigrationStartController" fx:controller="org.cryptomator.ui.migration.MigrationStartController"
prefWidth="580" prefWidth="580"
prefHeight="350" prefHeight="350"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -15,7 +15,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -16,7 +16,8 @@
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.notification.NotificationController" fx:controller="org.cryptomator.ui.notification.NotificationController"
prefHeight="200.0" prefWidth="400.0" maxHeight="200.0" maxWidth="400.0" prefHeight="200.0" prefWidth="400.0" maxHeight="200.0" maxWidth="400.0"
styleClass="notification-window"> styleClass="notification-window"
accessibleRole="DIALOG">
<padding> <padding>
<Insets top="12" right="12" bottom="12" left="12"/> <Insets top="12" right="12" bottom="12" left="12"/>
</padding> </padding>
+2 -1
View File
@@ -19,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -19,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -20,7 +20,8 @@
maxWidth="400" maxWidth="400"
minHeight="175" minHeight="175"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -14,7 +14,8 @@
minWidth="350" minWidth="350"
minHeight="280" minHeight="280"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<children> <children>
<FormattedLabel format="%recoveryKey.display.description" arg1="${controller.vaultName}" wrapText="true" labelFor="$textarea"/> <FormattedLabel format="%recoveryKey.display.description" arg1="${controller.vaultName}" wrapText="true" labelFor="$textarea"/>
@@ -22,7 +22,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -25,7 +25,8 @@
prefWidth="480" prefWidth="480"
minHeight="242" minHeight="242"
spacing="12" spacing="12"
VBox.vgrow="ALWAYS"> VBox.vgrow="ALWAYS"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -17,7 +17,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -17,7 +17,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -12,7 +12,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_CENTER"> alignment="TOP_CENTER"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -10,28 +10,29 @@
fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyValidateController" fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyValidateController"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<children> <children>
<FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true" labelFor="$textarea"/> <FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true" labelFor="$textarea"/>
<TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/> <TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/>
<VBox> <VBox>
<Label text="Just some Filler" visible="false" managed="${textarea.text.empty}" graphicTextGap="6"> <Label text="%recoveryKey.recover.wrongKey" visible="false" managed="${textarea.text.empty}" graphicTextGap="6" wrapText="true" >
<graphic> <graphic>
<FontAwesome5IconView glyph="ANCHOR"/> <FontAwesome5IconView glyph="ANCHOR"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}"> <Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}">
<graphic> <graphic>
<FontAwesome5IconView glyph="CHECK"/> <FontAwesome5IconView glyph="CHECK"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}"> <Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}">
<graphic> <graphic>
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/> <FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}"> <Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}">
<graphic> <graphic>
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/> <FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
</graphic> </graphic>
+2 -1
View File
@@ -21,7 +21,8 @@
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.sharevault.ShareVaultController" fx:controller="org.cryptomator.ui.sharevault.ShareVaultController"
prefWidth="540" prefWidth="540"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -17,7 +17,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -19,7 +19,8 @@
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>

Some files were not shown because too many files have changed in this diff Show More