Skip to content

Commit 234fd63

Browse files
committed
Merge branch 'master' into f_vault4
2 parents e9d666c + 7a7adbf commit 234fd63

37 files changed

Lines changed: 949 additions & 611 deletions

File tree

README.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ This ensures that your data will always remain secure.
5050

5151
> [!TIP]
5252
> The purpose of SecureFolderFS is to provide a professional, usable 'safe folder' experience that supports all major platforms with a consistent feature set.
53-
> SecureFolderFS can run on a huge range of devices (as supported by Uno Platform, MAUI and the .NET Runtime).
53+
> SecureFolderFS can run on a huge range of devices (as supported by Uno Platform, .NET MAUI, and the .NET Runtime).
5454
5555
### How to use SecureFolderFS
5656

@@ -69,8 +69,8 @@ From the app's UI, you can create new vaults to store items securely.
6969
</p>
7070

7171
> *Upon entering the correct password, the vault will then open.*
72-
> *You can press 'View vault' to open the vault's mounted file-system in your file manager of choice.*
73-
> *When you're done accessing your files, you can press the 'Lock vault' button and the vault file-system will close.*
72+
> *You can press 'View vault' to open the vault's mounted file system in your file manager of choice.*
73+
> *When you're done accessing your files, you can press the 'Lock vault' button, and the vault file system will close.*
7474
> *The vault remains on your disk and your data is encrypted in a way that cannot be accessed by any program, past, present or future.*
7575
7676
## Contributing
@@ -83,15 +83,17 @@ Take a look at our *[contributing guidelines](CONTRIBUTING.md)* to learn about b
8383

8484
You can update existing localization strings by heading to our *[Crowdin project page](https://crowdin.com/project/securefolderfs)*.
8585
To add a new language to the list, please request it to be added *[here](https://github.com/securefolderfs-community/SecureFolderFS/issues/50)*.
86-
New translations will be synchronized periodically to the source code, and new releases will always contain the latest translations.
86+
New translations will be synchronized periodically with the source code, and new releases will always contain the latest translations.
87+
88+
For help with translating custom-format strings with pluralization support, refer to the [Localization Playground](https://github.com/securefolderfs-community/LocalizationPlayground) repository.
8789

8890
---
8991

9092
## Building from source
9193

9294
> [!NOTE]
9395
> Below are the instructions for building SecureFolderFS for a cross-platform target.
94-
> For other projects, such as the SDK, libraries and CLI program, you can build as normal with the latest .NET SDK, without the prerequisites listed below.
96+
> For other projects, such as the SDK, libraries, and CLI program, you can build as normal with the latest .NET SDK, without the prerequisites listed below.
9597
9698
### 1. Prerequisites
9799

@@ -104,7 +106,7 @@ New translations will be synchronized periodically to the source code, and new r
104106
- For iOS builds:
105107
- Xcode 26.2 (on macOS)
106108

107-
### 2. Set up IDE
109+
### 2. Set up the IDE
108110

109111
> [!TIP]
110112
> *Using Visual Studio 2026 is recommended for SecureFolderFS development.*
@@ -130,7 +132,7 @@ New translations will be synchronized periodically to the source code, and new r
130132
### 3. Run `Uno.Check`
131133

132134
> [!TIP]
133-
> *This step is optional, but is good practice to check you installed all the necessary dependencies to build SecureFolderFS on your computer.*
135+
> *This step is optional, but it is good practice to check that you installed all the necessary dependencies to build SecureFolderFS on your computer.*
134136
135137
Run the following command and follow all of its instructions (you need to have `Uno.Check` installed!)
136138

@@ -154,13 +156,13 @@ cd SecureFolderFS
154156
### 5. Build the project
155157

156158
- Open the solution `SecureFolderFS.Public.slnx`
157-
- Set `SecureFolderFS.Uno` as the startup project if you are building for desktop targets (i.e. macOS, Linux or Windows)
158-
- Set `SecureFolderFS.Maui` as the startup project if you are building for mobile targets (i.e. Android, iOS or iPadOS)
159-
- Select the appropriate target device / platform
159+
- Set `SecureFolderFS.Uno` as the startup project if you are building for desktop targets (i.e., macOS, Linux, or Windows)
160+
- Set `SecureFolderFS.Maui` as the startup project if you are building for mobile targets (i.e., Android, iOS, or iPadOS)
161+
- Select the appropriate target device/platform
160162
- Run with debugger
161163

162164
---
163165

164166
<p align="center">
165167
<img src=".github/assets/SecureFolderFS_Hero.png" />
166-
</p>
168+
</p>

src/Platforms/SecureFolderFS.Maui/Platforms/Android/ServiceImplementation/VaultForegroundService.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ private void UpdateNotification()
103103
var title = count switch
104104
{
105105
0 => "VaultUnlocked".ToLocalized(),
106-
1 => "OneVaultIsUnlocked".ToLocalized(),
107-
_ => "MultipleVaultsAreUnlocked".ToLocalized(count)
106+
_ => "VaultsUnlockedPlural".ToLocalized(count)
108107
};
109108

110109
// Tapping the notification brings the app back to foreground

src/Platforms/SecureFolderFS.Maui/UserControls/Browser/BrowserControl.DragDrop.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ await transferViewModel.TransferAsync(itemsToProcess, async (item, reporter, tok
461461
new FileViewModel(createdFile, browserViewModel, destinationViewModel),
462462
browserViewModel.Layouts.GetSorter());
463463
}
464-
}, cts.Token);
464+
}, x => x.Name, cts.Token);
465465
}
466466
catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
467467
{

src/Platforms/SecureFolderFS.Maui/UserControls/Browser/TransferControl.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
<uc:AnimatedRevealLayout.MainContent>
5757
<Label
5858
FontSize="16"
59+
LineBreakMode="TailTruncation"
5960
Text="{Binding Title, Mode=OneWay}"
6061
VerticalOptions="Center" />
6162
</uc:AnimatedRevealLayout.MainContent>

src/Platforms/SecureFolderFS.Maui/Views/Vault/BrowserPage.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
FontSize="18"
5151
HorizontalOptions="Center"
5252
IsVisible="{Binding ViewModel.IsSelecting, Mode=OneWay}"
53-
Text="{Binding ViewModel.CurrentFolder.SelectedItems.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(0:LOCALIZE|SelectItems)|(>0:LOCALIZE|ItemsSelected)'}"
53+
Text="{Binding ViewModel.CurrentFolder.SelectedItems.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(0:LOCALIZE|SelectItems)|(>0:LOCALIZE|ItemsSelectedPlural)'}"
5454
TextColor="#FFFFFF"
5555
VerticalOptions="Center" />
5656
<VerticalStackLayout IsVisible="{Binding ViewModel.IsSelecting, Mode=OneWay, Converter={StaticResource BoolInvertConverter}}" VerticalOptions="Center">
@@ -62,7 +62,7 @@
6262
<Label
6363
FontSize="12"
6464
Opacity="0.6"
65-
Text="{Binding ViewModel.CurrentFolder.Items.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|ElementsCount)'}"
65+
Text="{Binding ViewModel.CurrentFolder.Items.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|ElementsCountPlural)'}"
6666
TextColor="#FFFFFF" />
6767
</VerticalStackLayout>
6868
</Grid>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
SmartFormat
2+
https://github.com/axuno/SmartFormat/blob/main/LICENSE.md
3+
MIT
4+
https://github.com/axuno/SmartFormat
5+
6+
The MIT License (MIT)
7+
=====================
8+
9+
Copyright © 2011-2022 SmartFormat Project maintainers and contributors.
10+
11+
All rights reserved.
12+
13+
* Project founder: Scott Rippey
14+
* Project owner: axuno gGmbH
15+
16+
Permission is hereby granted, free of charge, to any person
17+
obtaining a copy of this software and associated documentation
18+
files (the “Software”), to deal in the Software without
19+
restriction, including without limitation the rights to use,
20+
copy, modify, merge, publish, distribute, sublicense, and/or sell
21+
copies of the Software, and to permit persons to whom the
22+
Software is furnished to do so, subject to the following
23+
conditions:
24+
25+
The above copyright notice and this permission notice shall be
26+
included in all copies or substantial portions of the Software.
27+
28+
THE SOFTWARE IS PROVIDED ìAS “IS”, WITHOUT WARRANTY OF ANY KIND,
29+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
30+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
32+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
33+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
35+
OTHER DEALINGS IN THE SOFTWARE.
36+
37+
---
38+
39+
The bundled project *SmartFormat.ZString* is Copyright © Cysharp, Inc. [Their software](https://github.com/Cysharp/ZString)
40+
is licensed under [The MIT License (MIT)](src/SmartFormat.ZString/repo/LICENSE).
41+
Their conversion methods under the `ZString/Number` directory
42+
is Copyright © .NET Foundation and Contributors und is licensed
43+
under [The MIT License (MIT)](https://github.com/dotnet/runtime/blob/master/LICENSE.TXT).

src/Platforms/SecureFolderFS.UI/Strings/cs-CZ/Resources.resx

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,6 @@
620620
<data name="DateToday" xml:space="preserve">
621621
<value>Today, {0}</value>
622622
</data>
623-
<data name="DateAgo" xml:space="preserve">
624-
<value>{0} ago</value>
625-
</data>
626623
<data name="ErrorOccurred" xml:space="preserve">
627624
<value>An error occurred</value>
628625
</data>
@@ -1043,11 +1040,11 @@
10431040
<data name="DateYesterday" xml:space="preserve">
10441041
<value>Yesterday, {0}</value>
10451042
</data>
1046-
<data name="DateWeekAgo" xml:space="preserve">
1047-
<value>Last week</value>
1043+
<data name="DateWeekAgoPlural" xml:space="preserve">
1044+
<value>{0:plural:Last week|{} weeks ago|{} weeks ago}</value>
10481045
</data>
1049-
<data name="DateDaysAgo" xml:space="preserve">
1050-
<value>{0} days ago</value>
1046+
<data name="DateDaysAgoPlural" xml:space="preserve">
1047+
<value>{0:plural:{} day ago|{} days ago|{} days ago}</value>
10511048
</data>
10521049
<data name="VaultUnlocked" xml:space="preserve">
10531050
<value>Vault is unlocked</value>
@@ -1085,8 +1082,8 @@
10851082
<data name="FileHasCorruptedChunks" xml:space="preserve">
10861083
<value>Parts of the file are corrupted and will be reset</value>
10871084
</data>
1088-
<data name="CorruptedChunks" xml:space="preserve">
1089-
<value>{0} corrupted region(s)</value>
1085+
<data name="CorruptedChunksPlural" xml:space="preserve">
1086+
<value>{0:plural:{} corrupted region|{} corrupted regions|{} corrupted regions}</value>
10901087
</data>
10911088
<data name="DataLossImminent" xml:space="preserve">
10921089
<value>Data loss unpreventable</value>
@@ -1178,26 +1175,26 @@
11781175
<data name="ClearSelection" xml:space="preserve">
11791176
<value>Clear selection</value>
11801177
</data>
1181-
<data name="CopyingItems" xml:space="preserve">
1182-
<value>Copying {0} item(s)</value>
1178+
<data name="CopyingItemsPlural" xml:space="preserve">
1179+
<value>Copying {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
11831180
</data>
1184-
<data name="MovingItems" xml:space="preserve">
1185-
<value>Moving {0} item(s)</value>
1181+
<data name="MovingItemsPlural" xml:space="preserve">
1182+
<value>Moving {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
11861183
</data>
1187-
<data name="DeletingItems" xml:space="preserve">
1188-
<value>Deleting {0} item(s)</value>
1184+
<data name="DeletingItemsPlural" xml:space="preserve">
1185+
<value>Deleting {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
11891186
</data>
11901187
<data name="NotEnoughSpace" xml:space="preserve">
11911188
<value>Not enough space</value>
11921189
</data>
11931190
<data name="ItemDeletionTitle" xml:space="preserve">
11941191
<value>Deleting item(s)</value>
11951192
</data>
1196-
<data name="ItemDeletionDescription" xml:space="preserve">
1197-
<value>Are you sure you want to permanently delete {0} item(s)?</value>
1193+
<data name="ItemDeletionDescriptionPlural" xml:space="preserve">
1194+
<value>Are you sure you want to permanently delete {0:plural:one item|{} items|{} items}?</value>
11981195
</data>
1199-
<data name="ItemsExceedRecycleBinSize" xml:space="preserve">
1200-
<value>The deleted items exceed the available space in the recycle bin. Do you want to permanently delete {0} item(s) instead?</value>
1196+
<data name="ItemsExceedRecycleBinSizePlural" xml:space="preserve">
1197+
<value>The deleted {0:plural:item exceeds|{} items exceed|{} items exceed} the available space in the recycle bin. Do you want to permanently delete {0:plural:this item|{} items|{} items} instead?</value>
12011198
</data>
12021199
<data name="IntroPrefix" xml:space="preserve">
12031200
<value>By continuing, you agree to our </value>
@@ -1229,14 +1226,14 @@
12291226
<data name="EnableDeviceLink" xml:space="preserve">
12301227
<value>Enable Device Link</value>
12311228
</data>
1232-
<data name="ItemsSelected" xml:space="preserve">
1233-
<value>{0} item(s) selected</value>
1229+
<data name="ItemsSelectedPlural" xml:space="preserve">
1230+
<value>{0:plural:One item|{} items|{} items} selected</value>
12341231
</data>
1235-
<data name="ElementsCount" xml:space="preserve">
1236-
<value>{0} element(s)</value>
1232+
<data name="ElementsCountPlural" xml:space="preserve">
1233+
<value>{0:plural:{} element|{} elements|{} elements}</value>
12371234
</data>
1238-
<data name="FoundIssuesCount" xml:space="preserve">
1239-
<value>Found {0} issue(s)</value>
1235+
<data name="FoundIssuesCountPlural" xml:space="preserve">
1236+
<value>Found {0:plural:one issue|{} issues|{} issues}</value>
12401237
</data>
12411238
<data name="AvailableWidgets" xml:space="preserve">
12421239
<value>Available widgets</value>
@@ -1256,8 +1253,8 @@
12561253
<data name="ArchiveFormatNotSupported" xml:space="preserve">
12571254
<value>This archive format is not supported for extraction</value>
12581255
</data>
1259-
<data name="ExtractingItems" xml:space="preserve">
1260-
<value>Extracting {0} items</value>
1256+
<data name="ExtractingItemsPlural" xml:space="preserve">
1257+
<value>Extracting {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
12611258
</data>
12621259
<data name="Extracting" xml:space="preserve">
12631260
<value>Extracting...</value>
@@ -1332,7 +1329,7 @@
13321329
<value>Manual certificate fingerprint (SHA-256)</value>
13331330
</data>
13341331
<data name="SearchIn" xml:space="preserve">
1335-
<value>Search in: {0}</value>
1332+
<value>Search in: '{0}'</value>
13361333
</data>
13371334
<data name="RootFolder" xml:space="preserve">
13381335
<value>Root folder</value>
@@ -1346,8 +1343,8 @@
13461343
<data name="CollectingItemsCount" xml:space="preserve">
13471344
<value>Collecting items ({0})</value>
13481345
</data>
1349-
<data name="CollectedCountItems" xml:space="preserve">
1350-
<value>Collected {0} items</value>
1346+
<data name="CollectedItemsPlural" xml:space="preserve">
1347+
<value>Collected {0:plural:{} item|{} items|{} items}</value>
13511348
</data>
13521349
<data name="ScanCompleted" xml:space="preserve">
13531350
<value>Scan completed</value>
@@ -1421,16 +1418,37 @@
14211418
<data name="TapToLockAll" xml:space="preserve">
14221419
<value>Tap to lock all vaults</value>
14231420
</data>
1424-
<data name="OneVaultIsUnlocked" xml:space="preserve">
1425-
<value>One vault is unlocked</value>
1426-
</data>
1427-
<data name="MultipleVaultsAreUnlocked" xml:space="preserve">
1428-
<value>{0} vaults are unlocked</value>
1421+
<data name="VaultsUnlockedPlural" xml:space="preserve">
1422+
<value>{0:plural:One vault is|{} vaults are|{} vaults are} unlocked</value>
14291423
</data>
14301424
<data name="ViewInApp" xml:space="preserve">
14311425
<value>View in app</value>
14321426
</data>
14331427
<data name="ExitApp" xml:space="preserve">
14341428
<value>Exit</value>
14351429
</data>
1430+
<data name="Vault" xml:space="preserve">
1431+
<value>Vault</value>
1432+
</data>
1433+
<data name="SaveCredentials" xml:space="preserve">
1434+
<value>Save credentials</value>
1435+
</data>
1436+
<data name="CharacterCount" xml:space="preserve">
1437+
<value>Characters: {0}</value>
1438+
</data>
1439+
<data name="CursorPosition" xml:space="preserve">
1440+
<value>Position: {0}</value>
1441+
</data>
1442+
<data name="FileModified" xml:space="preserve">
1443+
<value>Modified</value>
1444+
</data>
1445+
<data name="CredentialsHaveBeenSaved" xml:space="preserve">
1446+
<value>Credentials have been saved for this vault</value>
1447+
</data>
1448+
<data name="DiscardSavedCredentials" xml:space="preserve">
1449+
<value>Discard saved credentials</value>
1450+
</data>
1451+
<data name="OpenInExternalApp" xml:space="preserve">
1452+
<value>Open in external app</value>
1453+
</data>
14361454
</root>

0 commit comments

Comments
 (0)