Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ private void UpdateNotification()
var title = count switch
{
0 => "VaultUnlocked".ToLocalized(),
1 => "OneVaultIsUnlocked".ToLocalized(),
_ => "MultipleVaultsAreUnlocked".ToLocalized(count)
_ => "VaultsUnlockedPlural".ToLocalized(count)
Comment thread
d2dyno1 marked this conversation as resolved.
};

// Tapping the notification brings the app back to foreground
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ await transferViewModel.TransferAsync(itemsToProcess, async (item, reporter, tok
new FileViewModel(createdFile, browserViewModel, destinationViewModel),
browserViewModel.Layouts.GetSorter());
}
}, cts.Token);
}, x => x.Name, cts.Token);
}
catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
<uc:AnimatedRevealLayout.MainContent>
<Label
FontSize="16"
LineBreakMode="TailTruncation"
Text="{Binding Title, Mode=OneWay}"
VerticalOptions="Center" />
</uc:AnimatedRevealLayout.MainContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
FontSize="18"
HorizontalOptions="Center"
IsVisible="{Binding ViewModel.IsSelecting, Mode=OneWay}"
Text="{Binding ViewModel.CurrentFolder.SelectedItems.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(0:LOCALIZE|SelectItems)|(>0:LOCALIZE|ItemsSelected)'}"
Text="{Binding ViewModel.CurrentFolder.SelectedItems.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(0:LOCALIZE|SelectItems)|(>0:LOCALIZE|ItemsSelectedPlural)'}"
TextColor="#FFFFFF"
VerticalOptions="Center" />
<VerticalStackLayout IsVisible="{Binding ViewModel.IsSelecting, Mode=OneWay, Converter={StaticResource BoolInvertConverter}}" VerticalOptions="Center">
Expand All @@ -62,7 +62,7 @@
<Label
FontSize="12"
Opacity="0.6"
Text="{Binding ViewModel.CurrentFolder.Items.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|ElementsCount)'}"
Text="{Binding ViewModel.CurrentFolder.Items.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|ElementsCountPlural)'}"
TextColor="#FFFFFF" />
Comment thread
d2dyno1 marked this conversation as resolved.
</VerticalStackLayout>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
SmartFormat
https://github.com/axuno/SmartFormat/blob/main/LICENSE.md
MIT
https://github.com/axuno/SmartFormat

The MIT License (MIT)
=====================

Copyright © 2011-2022 SmartFormat Project maintainers and contributors.

All rights reserved.

* Project founder: Scott Rippey
* Project owner: axuno gGmbH

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the “Software”), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ìAS “IS”, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Comment thread
d2dyno1 marked this conversation as resolved.
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

---

The bundled project *SmartFormat.ZString* is Copyright © Cysharp, Inc. [Their software](https://github.com/Cysharp/ZString)
is licensed under [The MIT License (MIT)](src/SmartFormat.ZString/repo/LICENSE).
Their conversion methods under the `ZString/Number` directory
is Copyright © .NET Foundation and Contributors und is licensed
under [The MIT License (MIT)](https://github.com/dotnet/runtime/blob/master/LICENSE.TXT).
64 changes: 29 additions & 35 deletions src/Platforms/SecureFolderFS.UI/Strings/en-US/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,6 @@
<data name="DateToday" xml:space="preserve">
<value>Today, {0}</value>
</data>
<data name="DateAgo" xml:space="preserve">
<value>{0} ago</value>
</data>
<data name="ErrorOccurred" xml:space="preserve">
<value>An error occurred</value>
</data>
Expand Down Expand Up @@ -1043,11 +1040,11 @@
<data name="DateYesterday" xml:space="preserve">
<value>Yesterday, {0}</value>
</data>
<data name="DateWeekAgo" xml:space="preserve">
<value>Last week</value>
<data name="DateWeekAgoPlural" xml:space="preserve">
<value>{0:plural:Last week|{} weeks ago|{} weeks ago}</value>
</data>
<data name="DateDaysAgo" xml:space="preserve">
<value>{0} days ago</value>
<data name="DateDaysAgoPlural" xml:space="preserve">
<value>{0:plural:{} day ago|{} days ago|{} days ago}</value>
</data>
<data name="VaultUnlocked" xml:space="preserve">
<value>Vault is unlocked</value>
Expand Down Expand Up @@ -1085,8 +1082,8 @@
<data name="FileHasCorruptedChunks" xml:space="preserve">
<value>Parts of the file are corrupted and will be reset</value>
</data>
<data name="CorruptedChunks" xml:space="preserve">
<value>{0} corrupted region(s)</value>
<data name="CorruptedChunksPlural" xml:space="preserve">
<value>{0:plural:{} corrupted region|{} corrupted regions|{} corrupted regions}</value>
</data>
<data name="DataLossImminent" xml:space="preserve">
<value>Data loss unpreventable</value>
Expand Down Expand Up @@ -1178,26 +1175,26 @@
<data name="ClearSelection" xml:space="preserve">
<value>Clear selection</value>
</data>
<data name="CopyingItems" xml:space="preserve">
<value>Copying {0} item(s)</value>
<data name="CopyingItemsPlural" xml:space="preserve">
<value>Copying {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
</data>
<data name="MovingItems" xml:space="preserve">
<value>Moving {0} item(s)</value>
<data name="MovingItemsPlural" xml:space="preserve">
<value>Moving {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
</data>
<data name="DeletingItems" xml:space="preserve">
<value>Deleting {0} item(s)</value>
<data name="DeletingItemsPlural" xml:space="preserve">
<value>Deleting {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
</data>
<data name="NotEnoughSpace" xml:space="preserve">
<value>Not enough space</value>
</data>
<data name="ItemDeletionTitle" xml:space="preserve">
<value>Deleting item(s)</value>
</data>
<data name="ItemDeletionDescription" xml:space="preserve">
<value>Are you sure you want to permanently delete {0} item(s)?</value>
<data name="ItemDeletionDescriptionPlural" xml:space="preserve">
<value>Are you sure you want to permanently delete {0:plural:one item|{} items|{} items}?</value>
</data>
<data name="ItemsExceedRecycleBinSize" xml:space="preserve">
<value>The deleted items exceed the available space in the recycle bin. Do you want to permanently delete {0} item(s) instead?</value>
<data name="ItemsExceedRecycleBinSizePlural" xml:space="preserve">
<value>The deleted {0:plural:item exceeds|{} items exceed} the available space in the recycle bin. Do you want to permanently delete {0:plural:this item|{} items} instead?</value>
</data>
<data name="IntroPrefix" xml:space="preserve">
<value>By continuing, you agree to our </value>
Expand Down Expand Up @@ -1229,14 +1226,14 @@
<data name="EnableDeviceLink" xml:space="preserve">
<value>Enable Device Link</value>
</data>
<data name="ItemsSelected" xml:space="preserve">
<value>{0} item(s) selected</value>
<data name="ItemsSelectedPlural" xml:space="preserve">
<value>{0:plural:One item|{} items|{} items} selected</value>
</data>
<data name="ElementsCount" xml:space="preserve">
<value>{0} element(s)</value>
<data name="ElementsCountPlural" xml:space="preserve">
<value>{0:plural:{} element|{} elements}</value>
</data>
<data name="FoundIssuesCount" xml:space="preserve">
<value>Found {0} issue(s)</value>
<data name="FoundIssuesCountPlural" xml:space="preserve">
<value>Found {0:plural:one issue|{} issues}</value>
</data>
<data name="AvailableWidgets" xml:space="preserve">
<value>Available widgets</value>
Expand All @@ -1256,8 +1253,8 @@
<data name="ArchiveFormatNotSupported" xml:space="preserve">
<value>This archive format is not supported for extraction</value>
</data>
<data name="ExtractingItems" xml:space="preserve">
<value>Extracting {0} items</value>
<data name="ExtractingItemsPlural" xml:space="preserve">
<value>Extracting {Total:choose(0):{Achieved} {Achieved:plural:item|items|items}|{Total:choose(1):{State}|{Achieved}/{Total} {Total:plural:item|items|items}}}</value>
</data>
<data name="Extracting" xml:space="preserve">
<value>Extracting...</value>
Expand Down Expand Up @@ -1332,7 +1329,7 @@
<value>Manual certificate fingerprint (SHA-256)</value>
</data>
<data name="SearchIn" xml:space="preserve">
<value>Search in: {0}</value>
<value>Search in: '{0}'</value>
</data>
<data name="RootFolder" xml:space="preserve">
<value>Root folder</value>
Expand All @@ -1346,8 +1343,8 @@
<data name="CollectingItemsCount" xml:space="preserve">
<value>Collecting items ({0})</value>
</data>
<data name="CollectedCountItems" xml:space="preserve">
<value>Collected {0} items</value>
<data name="CollectedItemsPlural" xml:space="preserve">
<value>Collected {0:plural:{} item|{} items|{} items}</value>
</data>
<data name="ScanCompleted" xml:space="preserve">
<value>Scan completed</value>
Expand Down Expand Up @@ -1421,11 +1418,8 @@
<data name="TapToLockAll" xml:space="preserve">
<value>Tap to lock all vaults</value>
</data>
<data name="OneVaultIsUnlocked" xml:space="preserve">
<value>One vault is unlocked</value>
</data>
<data name="MultipleVaultsAreUnlocked" xml:space="preserve">
<value>{0} vaults are unlocked</value>
<data name="VaultsUnlockedPlural" xml:space="preserve">
<value>{0:plural:One vault is|{} vaults are|{} vaults are} unlocked</value>
</data>
<data name="ViewInApp" xml:space="preserve">
<value>View in app</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using SecureFolderFS.Sdk.Extensions;
using SecureFolderFS.Sdk.Services;
using SecureFolderFS.Shared;
using SecureFolderFS.Shared.Helpers;

namespace SecureFolderFS.UI.ValueConverters
{
Expand All @@ -19,7 +18,7 @@ public abstract class BaseDateTimeToStringConverter : BaseConverter
if (parameter is string formatString)
{
var split = formatString.Split('|');
if (split[0] == "LOCALIZE")
if (split[0].Equals("localize", StringComparison.OrdinalIgnoreCase))
return string.Format(split[1].ToLocalized(), dateString);
else
return string.Format(split[1], dateString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public HealthFileDataIssueViewModel(IStorableChild storable, IResult? result, st
{
Severity = Severity.Critical;
CorruptedChunks = corruptedChunks ?? [];
CorruptedChunksText = !isRecoverable ? string.Empty : "CorruptedChunks".ToLocalized(CorruptedChunks.Count);
CorruptedChunksText = !isRecoverable ? string.Empty : "CorruptedChunksPlural".ToLocalized(CorruptedChunks.Count);
Comment thread
d2dyno1 marked this conversation as resolved.
IsRecoverable = isRecoverable;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@
</Grid.RowDefinitions>

<InfoBar
Title="{x:Bind ViewModel.HealthViewModel.FoundIssues.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|FoundIssuesCount)'}"
Title="{x:Bind ViewModel.HealthViewModel.FoundIssues.Count, Mode=OneWay, Converter={StaticResource CountToStringConverter}, ConverterParameter='(>=0:LOCALIZE|FoundIssuesCountPlural)'}"
Comment thread
d2dyno1 marked this conversation as resolved.
Grid.Row="0"
VerticalContentAlignment="Center"
IsClosable="False"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
/// </summary>
/// <param name="Achieved">The current achieved progress so far.</param>
/// <param name="Total">The total progress to achieve.</param>
public readonly record struct TotalProgress(int Achieved, int Total);
/// <param name="State">The additional state of the progress.</param>
public readonly record struct TotalProgress(int Achieved, int Total, object? State = null);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using SecureFolderFS.Sdk.Services;
using SecureFolderFS.Shared;
using SecureFolderFS.Shared.Helpers;
using SmartFormat;

namespace SecureFolderFS.Sdk.Extensions
{
Expand Down Expand Up @@ -43,7 +44,7 @@ public static string ToLocalized(this string resourceKey, ILocalizationService?
public static string ToLocalized(this string resourceKey, params object?[] interpolate)
{
var localized = ToLocalized(resourceKey);
return SafetyHelpers.NoFailureResult(() => string.Format(localized, interpolate)) ?? localized;
return SafetyHelpers.NoFailureResult(() => Smart.Format(localized, interpolate)) ?? $"{{{resourceKey}}}";
}

/// <summary>
Expand All @@ -57,7 +58,7 @@ public static string ToLocalized(this string resourceKey, params object?[] inter
public static string ToLocalized(this string resourceKey, ILocalizationService localizationService, params object?[] interpolate)
{
var localized = ToLocalized(resourceKey, localizationService);
return SafetyHelpers.NoFailureResult(() => string.Format(localized, interpolate)) ?? localized;
return SafetyHelpers.NoFailureResult(() => Smart.Format(localized, interpolate)) ?? $"{{{resourceKey}}}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ public static string LocalizeDate(this ILocalizationService localizationService,
{
var cultureInfo = localizationService.CurrentCulture;
var daysAgo = (DateTime.Today - dateTime.Date).Days;
var weeksAgo = daysAgo / 7;
var dateString = dateTime switch
{
_ when dateTime.Year == 1 => "Unspecified",
_ when dateTime.Date == DateTime.Today => "DateToday".ToLocalized(localizationService, interpolate: dateTime.ToString("t", cultureInfo)),
_ when daysAgo == 1 => "DateYesterday".ToLocalized(localizationService, interpolate: dateTime.ToString("t", cultureInfo)),
_ when daysAgo is >= 2 and <= 6 => "DateDaysAgo".ToLocalized(localizationService, interpolate: daysAgo.ToString()),
_ when daysAgo is >= 7 and < 14 => "DateWeekAgo".ToLocalized(localizationService),
_ when daysAgo is >= 2 and <= 6 => "DateDaysAgoPlural".ToLocalized(localizationService, interpolate: daysAgo),
_ when daysAgo is >= 7 and < 14 => "DateWeekAgoPlural".ToLocalized(localizationService, interpolate: weeksAgo),
_ => null
Comment thread
d2dyno1 marked this conversation as resolved.
};

Expand Down
35 changes: 29 additions & 6 deletions src/Sdk/SecureFolderFS.Sdk/Extensions/TransferExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,39 @@ public static async Task TransferAsync<TTransferred>(
IEnumerable<TTransferred> items,
Func<TTransferred, IProgress<IStorable>, CancellationToken, Task> callback,
CancellationToken cancellationToken = default)
where TTransferred : IStorable
{
await TransferAsync(transferViewModel, items, callback, x => x.Name, cancellationToken);
}

public static async Task TransferAsync<TTransferred>(
this TransferViewModel transferViewModel,
IEnumerable<TTransferred> items,
Func<TTransferred, IProgress<IStorable>, CancellationToken, Task> callback,
Func<TTransferred, string> itemName,
CancellationToken cancellationToken = default)
{
var collection = items.ToOrAsCollection();
transferViewModel.IsProgressing = true;
transferViewModel.IsVisible = true;
transferViewModel.Report(new(0, 0));
transferViewModel.Report(new(0, collection.Count, collection.Count));
var counter = 0;
var reporter = new Progress<IStorable>(_ =>
var reporter = new Progress<IStorable>(x =>
{
counter++;
transferViewModel.Report(new(counter, 0));
transferViewModel.Report(new(counter, 0, x.Name));
});

for (var i = 0; i < collection.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();

var item = collection.ElementAt(i);
transferViewModel.Report(new(i, collection.Count, itemName(item)));
await callback(item, reporter, cancellationToken);
}

transferViewModel.Title = "TransferDone".ToLocalized();
transferViewModel.Report(new(collection.Count, collection.Count, string.Empty));
await Task.Delay(1000, CancellationToken.None);
await transferViewModel.HideAsync();
}
Expand All @@ -61,21 +73,32 @@ public static async Task TransferAsync<TTransferred>(
Func<TTransferred, CancellationToken, Task> callback,
CancellationToken cancellationToken = default)
where TTransferred : IStorable
{
await TransferAsync(transferViewModel, items, callback, x => x.Name, cancellationToken);
}

public static async Task TransferAsync<TTransferred>(
this TransferViewModel transferViewModel,
IEnumerable<TTransferred> items,
Func<TTransferred, CancellationToken, Task> callback,
Func<TTransferred, string> itemName,
CancellationToken cancellationToken = default)
{
var collection = items.ToOrAsCollection();
transferViewModel.IsProgressing = true;
transferViewModel.IsVisible = true;
transferViewModel.Report(new(0, collection.Count));
transferViewModel.Report(new(0, collection.Count, collection.Count));

for (var i = 0; i < collection.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();

var item = collection.ElementAt(i);
transferViewModel.Report(new(i, collection.Count, itemName(item)));
await callback(item, cancellationToken);
Comment thread
d2dyno1 marked this conversation as resolved.
transferViewModel.Report(new((i + 1), collection.Count));
}

transferViewModel.Report(new(collection.Count, collection.Count, string.Empty));
await Task.Delay(1000, CancellationToken.None);
await transferViewModel.HideAsync();
}
Expand Down
Loading
Loading