diff --git a/src/Besql/Bit.Besql/wwwroot/bit-besql.js b/src/Besql/Bit.Besql/wwwroot/bit-besql.js index 5ad9782aea..648c73cafa 100644 --- a/src/Besql/Bit.Besql/wwwroot/bit-besql.js +++ b/src/Besql/Bit.Besql/wwwroot/bit-besql.js @@ -1,5 +1,5 @@ var BitBesql = window.BitBesql || {}; -BitBesql.version = window['bit-besql version'] = '9.2.0'; +BitBesql.version = window['bit-besql version'] = '9.2.1'; BitBesql.init = async function init(fileName) { const sqliteFilePath = `/${fileName}`; diff --git a/src/Bit.Build.props b/src/Bit.Build.props index c690155096..a03e83e228 100644 --- a/src/Bit.Build.props +++ b/src/Bit.Build.props @@ -27,7 +27,7 @@ https://github.com/bitfoundation/bitplatform - 9.2.0 + 9.2.1 $(ReleaseVersion) https://github.com/bitfoundation/bitplatform/releases/tag/v-$(ReleaseVersion) $([System.String]::Copy($(ReleaseVersion)).Replace('-pre-', '.')) diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs index ce37361a0f..169e58db1d 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs @@ -9,7 +9,7 @@ namespace Bit.BlazorUI; /// integrates with an , which must be supplied /// as a cascading parameter. /// -public abstract class BitInputBase : BitComponentBase, IDisposable +public abstract class BitInputBase : BitComponentBase, IDisposable, IAsyncDisposable { protected bool IsDisposed; protected bool ValueHasBeenSet; @@ -63,6 +63,11 @@ protected BitInputBase() /// [Parameter] public string? Name { get; set; } + /// + /// Disables the validation of the input. + /// + [Parameter] public bool NoValidate { get; set; } + /// /// Callback for when the input value changes. /// @@ -141,6 +146,11 @@ public override Task SetParametersAsync(ParameterView parameters) { switch (parameter.Key) { + case nameof(NoValidate): + NoValidate = (bool)parameter.Value; + parametersDictionary.Remove(parameter.Key); + break; + case nameof(CascadedEditContext): CascadedEditContext = (EditContext?)parameter.Value; parametersDictionary.Remove(parameter.Key); @@ -198,26 +208,29 @@ public override Task SetParametersAsync(ParameterView parameters) } } - if (_hasInitializedParameters is false) + if (NoValidate is false) { - // This is the first run - // Could put this logic in OnInit, but its nice to avoid forcing people who override OnInitialized to call base.OnInitialized() + if (_hasInitializedParameters is false) + { + // This is the first run + // Could put this logic in OnInitialized, but its nice to avoid forcing people who override OnInitialized to call base.OnInitialized() - CreateFieldIdentifier(); + CreateFieldIdentifier(); - _hasInitializedParameters = true; - } - else if (CascadedEditContext != EditContext) - { - // Not the first run + _hasInitializedParameters = true; + } + else if (CascadedEditContext != EditContext) + { + // Not the first run - // We don't support changing EditContext because it's messy to be clearing up state and event - // handlers for the previous one, and there's no strong use case. If a strong use case - // emerges, we can consider changing this. - throw new InvalidOperationException($"{GetType()} does not support changing the {nameof(EditContext)} dynamically."); - } + // We don't support changing EditContext because it's messy to be clearing up state and event + // handlers for the previous one, and there's no strong use case. If a strong use case + // emerges, we can consider changing this. + throw new InvalidOperationException($"{GetType()} does not support changing the {nameof(EditContext)} dynamically."); + } - UpdateValidationAttributes(); + UpdateValidationAttributes(); + } // For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc. return base.SetParametersAsync(ParameterView.FromDictionary(parametersDictionary!)); @@ -334,7 +347,7 @@ protected async Task SetCurrentValueAsStringAsync(string? value, bool bypass = f await SetCurrentValueAsync(parsedValue); } } - else + else if (NoValidate is false) { _parsingFailed = true; @@ -348,6 +361,10 @@ protected async Task SetCurrentValueAsStringAsync(string? value, bool bypass = f EditContext.NotifyFieldChanged(FieldIdentifier); } } + else + { + _parsingFailed = false; + } // We can skip the validation notification if we were previously valid and still are if (_parsingFailed || _previousParsingAttemptFailed) @@ -365,7 +382,10 @@ protected async Task SetCurrentValueAsync(TValue? value) await ValueChanged.InvokeAsync(value); - EditContext?.NotifyFieldChanged(FieldIdentifier); + if (EditContext is not null && NoValidate is false) + { + EditContext.NotifyFieldChanged(FieldIdentifier); + } await OnChange.InvokeAsync(value); } @@ -388,7 +408,7 @@ private void OnValidateStateChanged(object? sender, ValidationStateChangedEventA private void UpdateValidationAttributes() { - if (EditContext is null) return; + if (EditContext is null || NoValidate) return; var hasAriaInvalidAttribute = InputHtmlAttributes is not null && InputHtmlAttributes.ContainsKey("aria-invalid"); @@ -476,5 +496,15 @@ public void Dispose() GC.SuppressFinalize(this); } + public ValueTask DisposeAsync() + { + if (IsDisposed) return ValueTask.CompletedTask; + + Dispose(); + return DisposeAsync(true); + } + protected virtual void Dispose(bool disposing) { } + + protected virtual ValueTask DisposeAsync(bool disposing) { return ValueTask.CompletedTask; } } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs index 921e04a15e..bc15b8fae4 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs @@ -3,7 +3,7 @@ namespace Bit.BlazorUI; -public partial class BitOtpInput : BitInputBase, IDisposable +public partial class BitOtpInput : BitInputBase { private string _labelId = default!; private string?[] _inputIds = default!; @@ -116,14 +116,16 @@ public partial class BitOtpInput : BitInputBase, IDisposable /// public ValueTask FocusAsync(int index = 0) => _inputRefs[index].FocusAsync(); - [JSInvokable] - public async Task SetPastedData(string pastedValue) + + + [JSInvokable("SetValue")] + public async Task _SetValue(string value) { if (IsEnabled is false || InvalidValueBinding()) return; - if (pastedValue.HasNoValue()) return; - if (Type is BitInputType.Number && int.TryParse(pastedValue, out _) is false) return; + if (value.HasNoValue()) return; + if (Type is BitInputType.Number && int.TryParse(value, out _) is false) return; - SetInputsValue(pastedValue); + SetInputsValue(value); CurrentValueAsString = string.Join(string.Empty, _inputValues); @@ -195,7 +197,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) foreach (var inputRef in _inputRefs) { - await _js.BitOtpInputSetup(_dotnetObj, inputRef); + await _js.BitOtpInputSetup(_Id, _dotnetObj, inputRef); } } @@ -206,11 +208,12 @@ protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(fa return true; } - protected override void Dispose(bool disposing) + protected override async ValueTask DisposeAsync(bool disposing) { if (disposing) { _dotnetObj?.Dispose(); + await _js.BitOtpInputDispose(_Id); } base.Dispose(disposing); diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.ts b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.ts index cb59be3aa2..238d57bee2 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.ts +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.ts @@ -1,6 +1,8 @@ namespace BitBlazorUI { export class OtpInput { - public static setup(dotnetReference: DotNetObject, input: HTMLInputElement) { + private static abortControllers: { [key: string]: AbortController } = {}; + + public static setup(id: string, dotnetObj: DotNetObject, input: HTMLInputElement) { input.addEventListener('focus', (e: any) => { e.target?.select(); }); @@ -8,8 +10,37 @@ input.addEventListener('paste', async e => { e.preventDefault(); let pastedValue = e.clipboardData?.getData('Text'); - await dotnetReference.invokeMethodAsync("SetPastedData", pastedValue); + await dotnetObj.invokeMethodAsync("SetValue", pastedValue); }); + + OtpInput.setupSmsAutofill(id, dotnetObj); + } + + public static dispose(id: string) { + const ac = OtpInput.abortControllers[id]; + if (!ac) return; + + ac.abort(); + delete OtpInput.abortControllers[id]; + } + + private static setupSmsAutofill(id: string, dotnetObj: DotNetObject) { + if (!('OTPCredential' in window)) return; + + const abortCtrl = new AbortController(); + OtpInput.abortControllers[id] = abortCtrl; + + navigator.credentials.get({ + otp: { transport: ['sms'] }, + signal: abortCtrl.signal + } as any).then(async (otp: any) => { + await dotnetObj.invokeMethodAsync("SetValue", otp.code); + abortCtrl.abort(); + delete OtpInput.abortControllers[id]; + }).catch(async (err: any) => { + abortCtrl.abort(); + delete OtpInput.abortControllers[id]; + }) } } } \ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInputJsRuntimeExtensions.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInputJsRuntimeExtensions.cs index 8f9986a5ec..f90b5b094b 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInputJsRuntimeExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInputJsRuntimeExtensions.cs @@ -2,8 +2,13 @@ internal static class BitOtpInputJsRuntimeExtensions { - internal static ValueTask BitOtpInputSetup(this IJSRuntime jsRuntime, DotNetObjectReference obj, ElementReference input) + internal static ValueTask BitOtpInputSetup(this IJSRuntime jsRuntime, string id, DotNetObjectReference obj, ElementReference input) { - return jsRuntime.InvokeVoid("BitBlazorUI.OtpInput.setup", obj, input); + return jsRuntime.InvokeVoid("BitBlazorUI.OtpInput.setup", id, obj, input); + } + + internal static ValueTask BitOtpInputDispose(this IJSRuntime jsRuntime, string id) + { + return jsRuntime.InvokeVoid("BitBlazorUI.OtpInput.dispose", id); } } diff --git a/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts b/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts index 8b3488d591..91bb860cf6 100644 --- a/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts +++ b/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts @@ -1,4 +1,4 @@ -(BitBlazorUI as any).version = (window as any)['bit-blazorui version'] = '9.2.0'; +(BitBlazorUI as any).version = (window as any)['bit-blazorui version'] = '9.2.1'; interface DotNetObject { invokeMethod(methodIdentifier: string, ...args: any[]): T; diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj index 7a31606a92..51022de413 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj index 918454cdc4..a3f0ec3e3b 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj index dfa709cee2..b27f07bb20 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj @@ -16,11 +16,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentDemo.razor.cs index 0491a6bfe9..1cb1153951 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentDemo.razor.cs @@ -183,6 +183,13 @@ public partial class ComponentDemo Description = "Gets or sets the name of the element. Allows access by name from the associated form.", }, new() + { + Name = "NoValidate", + Type = "bool", + DefaultValue = "false", + Description = "Disables the validation of the input.", + }, + new() { Name = "OnChange", Type = "EventCallback", diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor index 7fd4783c85..03da47616c 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor @@ -46,7 +46,7 @@ -
+
@@ -72,4 +72,65 @@ + + +
An illustrative example of integrating this component into a straightforward mobile application.
+
+
+
+ +
+ + + + + BlazorUI + + + +
+
+ +
+ @foreach (var (idx, i) in advancedItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
+
+
+
+
+
+ + + +
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.
+

+
+ +
+ @foreach (var (idx, i) in styleItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+ + +
+ @foreach (var (idx, i) in classItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
+
+
+ \ No newline at end of file diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.cs index 75e72ebc52..76641be9a9 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.cs @@ -19,6 +19,15 @@ public partial class BitPullToRefreshDemo Description = "The anchor element that the pull to refresh component adheres to.", }, new() + { + Name = "Classes", + Type = "BitPullToRefreshClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the BitPullToRefresh.", + LinkType = LinkType.Link, + Href = "#class-styles", + }, + new() { Name = "Factor", Type = "decimal", @@ -84,6 +93,15 @@ public partial class BitPullToRefreshDemo Description = "The CSS selector of the element that is the scroller in the anchor to control the behavior of the pull to refresh.", }, new() + { + Name = "Styles", + Type = "BitPullToRefreshClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the BitPullToRefresh.", + LinkType = LinkType.Link, + Href = "#class-styles", + }, + new() { Name = "Threshold", Type = "int", @@ -96,7 +114,7 @@ public partial class BitPullToRefreshDemo Type = "int", DefaultValue = "80", Description = "The pulling height in pixel that triggers the refresh.", - }, + } ]; private readonly List componentSubClasses = @@ -127,6 +145,56 @@ public partial class BitPullToRefreshDemo }, ] }, + new() + { + Id = "class-styles", + Title = "BitPullToRefreshClassStyles", + Parameters = + [ + new() + { + Name = "Root", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the root element of the PullToRefresh." + }, + new() + { + Name = "Loading", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the loading element." + }, + new() + { + Name = "SpinnerWrapper", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the spinner wrapper element." + }, + new() + { + Name = "SpinnerWrapperRefreshing", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the spinner wrapper element in refreshing mode." + }, + new() + { + Name = "Spinner", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the spinner element." + }, + new() + { + Name = "SpinnerRefreshing", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the spinner element in refreshing mode." + }, + ] + } ]; @@ -154,6 +222,7 @@ private async Task HandleOnRefresh1() multiItems1 = GenerateRandomNumbers(1, 51); _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); } + private (int, int)[] multiItems2 = GenerateRandomNumbers(51, 101); private async Task HandleOnRefresh2() { @@ -162,152 +231,34 @@ private async Task HandleOnRefresh2() _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); } - - private static (int, int)[] GenerateRandomNumbers(int min, int max) + private (int, int)[] advancedItems = GenerateRandomNumbers(1, 51); + private async Task HandleOnRefreshAdvanced() { - var random = new Random(); - return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); + await Task.Delay(2000); + advancedItems = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); } - - private readonly string example1RazorCode = @" - - -
- @foreach (var (idx, i) in basicItems) - { -
@(idx.ToString().PadLeft(2, '0')). Item @i
- } -
-
"; - private readonly string example1CsharpCode = @" -private (int, int)[] basicItems = GenerateRandomNumbers(1, 51); -private async Task HandleOnRefreshBasic() -{ - await Task.Delay(2000); - basicItems = GenerateRandomNumbers(1, 51); - _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); -} - -private static (int, int)[] GenerateRandomNumbers(int min, int max) -{ - var random = new Random(); - return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); -}"; - - private readonly string example2RazorCode = @" - - - -
- @foreach (var (idx, i) in customItems) - { -
@(idx.ToString().PadLeft(2, '0')). Item @i
- } -
-
- - - - - - - - -
"; - private readonly string example2CsharpCode = @" -private (int, int)[] customItems = GenerateRandomNumbers(1, 51); -private async Task HandleOnRefreshCustom() -{ - await Task.Delay(2000); - customItems = GenerateRandomNumbers(1, 51); - _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); -} - -private static (int, int)[] GenerateRandomNumbers(int min, int max) -{ - var random = new Random(); - return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); -}"; - private readonly string example3RazorCode = @" - - -
-
- -
- @foreach (var (idx, i) in multiItems1) - { -
@(idx.ToString().PadLeft(2, '0')). Item @i
- } -
-
-
- -
- -
- @foreach (var (idx, i) in multiItems2) - { -
@(idx.ToString().PadLeft(2, '0')). Item @i
- } -
-
-
-
"; - private readonly string example3CsharpCode = @" -private (int, int)[] multiItems1 = GenerateRandomNumbers(0, 50); -private async Task HandleOnRefresh1() -{ - await Task.Delay(2000); - multiItems1 = GenerateRandomNumbers(1, 51); - _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); -} -private (int, int)[] multiItems2 = GenerateRandomNumbers(51, 101); -private async Task HandleOnRefresh2() -{ - await Task.Delay(2000); - multiItems2 = GenerateRandomNumbers(51, 101); - _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); -} - -private static (int, int)[] GenerateRandomNumbers(int min, int max) -{ - var random = new Random(); - return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); -}"; - } diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.samples.cs new file mode 100644 index 0000000000..3778230a0e --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.samples.cs @@ -0,0 +1,285 @@ +namespace Bit.BlazorUI.Demo.Client.Core.Pages.Components.Utilities.PullToRefresh; + +public partial class BitPullToRefreshDemo +{ + private readonly string example1RazorCode = @" + + + +
+ @foreach (var (idx, i) in basicItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
"; + private readonly string example1CsharpCode = @" +private (int, int)[] basicItems = GenerateRandomNumbers(1, 51); +private async Task HandleOnRefreshBasic() +{ + await Task.Delay(2000); + basicItems = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private static (int, int)[] GenerateRandomNumbers(int min, int max) +{ + var random = new Random(); + return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); +}"; + + private readonly string example2RazorCode = @" + + + + +
+ @foreach (var (idx, i) in customItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+ + + + + + + + +
"; + private readonly string example2CsharpCode = @" +private (int, int)[] customItems = GenerateRandomNumbers(1, 51); +private async Task HandleOnRefreshCustom() +{ + await Task.Delay(2000); + customItems = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private static (int, int)[] GenerateRandomNumbers(int min, int max) +{ + var random = new Random(); + return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); +}"; + + private readonly string example3RazorCode = @" + + +
+
+ +
+ @foreach (var (idx, i) in multiItems1) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
+ +
+ +
+ @foreach (var (idx, i) in multiItems2) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
+
"; + private readonly string example3CsharpCode = @" +private (int, int)[] multiItems1 = GenerateRandomNumbers(0, 50); +private async Task HandleOnRefresh1() +{ + await Task.Delay(2000); + multiItems1 = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} +private (int, int)[] multiItems2 = GenerateRandomNumbers(51, 101); +private async Task HandleOnRefresh2() +{ + await Task.Delay(2000); + multiItems2 = GenerateRandomNumbers(51, 101); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private static (int, int)[] GenerateRandomNumbers(int min, int max) +{ + var random = new Random(); + return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); +}"; + + private readonly string example4RazorCode = @" + + +
+
+ +
+ + + + + BlazorUI + + + +
+
+ +
+ @foreach (var (idx, i) in advancedItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
+
+
+
"; + private readonly string example4CsharpCode = @" +private (int, int)[] advancedItems = GenerateRandomNumbers(1, 51); +private async Task HandleOnRefreshAdvanced() +{ + await Task.Delay(2000); + advancedItems = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private static (int, int)[] GenerateRandomNumbers(int min, int max) +{ + var random = new Random(); + return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); +}"; + + private readonly string example5RazorCode = @" + + +
+ +
+ @foreach (var (idx, i) in styleItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+ + +
+ @foreach (var (idx, i) in classItems) + { +
@(idx.ToString().PadLeft(2, '0')). Item @i
+ } +
+
+
"; + private readonly string example5CsharpCode = @" +private (int, int)[] styleItems = GenerateRandomNumbers(1, 51); +private async Task HandleOnRefreshStyle() +{ + await Task.Delay(2000); + styleItems = GenerateRandomNumbers(1, 51); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private (int, int)[] classItems = GenerateRandomNumbers(51, 101); +private async Task HandleOnRefreshClass() +{ + await Task.Delay(2000); + classItems = GenerateRandomNumbers(51, 101); + _ = Task.Delay(1000).ContinueWith(_ => InvokeAsync(StateHasChanged)); +} + +private static (int, int)[] GenerateRandomNumbers(int min, int max) +{ + var random = new Random(); + return Enumerable.Range(min, max - min).Select(i => (i, random.Next(min, max))).ToArray(); +}"; + +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.scss index c11b6eeb5d..88c1e47c94 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.scss +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/PullToRefresh/BitPullToRefreshDemo.razor.scss @@ -1,4 +1,9 @@ -.anchor { +.example-content { + gap: 1rem; + display: flex; +} + +.anchor { width: 150px; padding: 4px; cursor: grab; @@ -8,5 +13,43 @@ border: 1px gray solid; } +.mobile-frame { + width: 300px; + height: 600px; + overflow: hidden; + position: relative; + border-radius: 36px; + border: 16px solid #333; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + background-color: var(--bit-clr-fg-sec); + + .screen { + width: 100%; + height: 100%; + } +} + +.advanced-anchor { + cursor: grab; + height: 490px; + overflow: auto; + user-select: none; +} + ::deep { + .custom-loading { + background-color: rgb(255, 106, 0, 0.1); + } + + .custom-spinner { + padding: 5px; + border-radius: 50%; + background-color: #ff6a00; + } + + .row { + color: black; + padding: 10px; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + } } diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Maui/Bit.BlazorUI.Demo.Client.Maui.csproj b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Maui/Bit.BlazorUI.Demo.Client.Maui.csproj index 84613c8e9b..e588bbba3e 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Maui/Bit.BlazorUI.Demo.Client.Maui.csproj +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Maui/Bit.BlazorUI.Demo.Client.Maui.csproj @@ -85,12 +85,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/Bit.BlazorUI.Demo.Client.Web.csproj b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/Bit.BlazorUI.Demo.Client.Web.csproj index 22b99f7095..3431bf36a6 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/Bit.BlazorUI.Demo.Client.Web.csproj +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/Bit.BlazorUI.Demo.Client.Web.csproj @@ -24,13 +24,13 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/wwwroot/service-worker.published.js b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/wwwroot/service-worker.published.js index 81ef753d81..63fe330a04 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/wwwroot/service-worker.published.js +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Web/wwwroot/service-worker.published.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 // https://github.com/bitfoundation/bitplatform/tree/develop/src/Bswup self.assetsInclude = []; diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Windows/Bit.BlazorUI.Demo.Client.Windows.csproj b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Windows/Bit.BlazorUI.Demo.Client.Windows.csproj index f548ce056b..3d98c0d8be 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Windows/Bit.BlazorUI.Demo.Client.Windows.csproj +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Windows/Bit.BlazorUI.Demo.Client.Windows.csproj @@ -29,11 +29,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Directory.Build.props b/src/BlazorUI/Demo/Directory.Build.props index c8d6effc67..52dab44bc7 100644 --- a/src/BlazorUI/Demo/Directory.Build.props +++ b/src/BlazorUI/Demo/Directory.Build.props @@ -1,4 +1,4 @@ - + 13.0 diff --git a/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.js b/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.js index 890ed88fee..ade0abcf81 100644 --- a/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.js +++ b/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 self.assetsExclude = [/\.scp\.css$/, /weather\.json$/]; self.caseInsensitiveUrl = true; diff --git a/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.published.js b/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.published.js index 25c8f5e457..2a3b911009 100644 --- a/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.published.js +++ b/src/Bswup/Bit.Bswup.Demo/wwwroot/service-worker.published.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 self.assetsExclude = [/\.scp\.css$/, /weather\.json$/]; self.caseInsensitiveUrl = true; diff --git a/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.js b/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.js index b5d48bb083..c89580de6b 100644 --- a/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.js +++ b/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 // In development, always fetch from the network and do not enable offline support. // This is because caching would make development more difficult (changes would not diff --git a/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.published.js b/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.published.js index 3d565b017b..c2e33884ae 100644 --- a/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.published.js +++ b/src/Bswup/Bit.Bswup.NewDemo/Bit.Bswup.NewDemo.Client/wwwroot/service-worker.published.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 self.assetsInclude = []; self.assetsExclude = [ diff --git a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.progress.ts b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.progress.ts index b440faf5ec..5f95ca03e3 100644 --- a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.progress.ts +++ b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.progress.ts @@ -1,4 +1,4 @@ -window['bit-bswup.progress version'] = '9.2.0'; +window['bit-bswup.progress version'] = '9.2.1'; ; (function () { (window as any).startBswupProgress = (autoReload: boolean, diff --git a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.sw.ts b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.sw.ts index 69d71fb174..e45d61beca 100644 --- a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.sw.ts +++ b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.sw.ts @@ -1,4 +1,4 @@ -self['bit-bswup.sw version'] = '9.2.0'; +self['bit-bswup.sw version'] = '9.2.1'; interface Window { clients: any @@ -233,7 +233,10 @@ async function createAssetsCache(ignoreProgressReport = false) { .concat(Object.keys(blazorBootJson.resources.runtime || {})) // before .NET 8 .concat(Object.keys(blazorBootJson.resources.jsModuleNative || {})) // after .NET 8 .concat(Object.keys(blazorBootJson.resources.jsModuleRuntime || {})) - .concat(Object.keys(blazorBootJson.resources.wasmNative || {})); + .concat(Object.keys(blazorBootJson.resources.wasmNative || {})) + .concat(Object.keys(blazorBootJson.resources.coreAssembly || {})) // after .NET 9 + .concat(Object.keys(blazorBootJson.resources.icu || {})) + .concat(Object.keys(blazorBootJson.resources.jsModuleGlobalization || {})); const blazorAssets = blazorResources.map(r => UNIQUE_ASSETS.find(a => a.url.endsWith(`/${r}`))).filter(a => !!a); diag('blazorBootAsset:', blazorBootAsset); diff --git a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.ts b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.ts index 42942a4e5e..27593681ff 100644 --- a/src/Bswup/Bit.Bswup/Scripts/bit-bswup.ts +++ b/src/Bswup/Bit.Bswup/Scripts/bit-bswup.ts @@ -1,5 +1,5 @@ const BitBswup = {} as any; -BitBswup.version = window['bit-bswup version'] = '9.2.0'; +BitBswup.version = window['bit-bswup version'] = '9.2.1'; declare const Blazor: any; diff --git a/src/Bswup/FullDemo/Client/wwwroot/service-worker.js b/src/Bswup/FullDemo/Client/wwwroot/service-worker.js index 9c6ed25336..6acf05acf6 100644 --- a/src/Bswup/FullDemo/Client/wwwroot/service-worker.js +++ b/src/Bswup/FullDemo/Client/wwwroot/service-worker.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 // In development, always fetch from the network and do not enable offline support. // This is because caching would make development more difficult (changes would not diff --git a/src/Bswup/FullDemo/Client/wwwroot/service-worker.published.js b/src/Bswup/FullDemo/Client/wwwroot/service-worker.published.js index 278f5178bb..6d64366f96 100644 --- a/src/Bswup/FullDemo/Client/wwwroot/service-worker.published.js +++ b/src/Bswup/FullDemo/Client/wwwroot/service-worker.published.js @@ -1,4 +1,4 @@ -// bit version: 9.2.0 +// bit version: 9.2.1 self.assetsInclude = []; self.assetsExclude = [/\.scp\.css$/, /weather\.json$/]; diff --git a/src/Bup/Bit.Bup/Scripts/bit-bup.progress.ts b/src/Bup/Bit.Bup/Scripts/bit-bup.progress.ts index 7139438816..8fb50f44a2 100644 --- a/src/Bup/Bit.Bup/Scripts/bit-bup.progress.ts +++ b/src/Bup/Bit.Bup/Scripts/bit-bup.progress.ts @@ -1,4 +1,4 @@ -window['bit-bup.progress version'] = '9.2.0'; +window['bit-bup.progress version'] = '9.2.1'; ; (function () { (window as any).startBupProgress = (showLogs: boolean, showAssets: boolean, appContainerSelector: string, hideApp: boolean, autoHide: boolean) => { diff --git a/src/Bup/Bit.Bup/Scripts/bit-bup.ts b/src/Bup/Bit.Bup/Scripts/bit-bup.ts index b3baa0162f..4eb481ea8f 100644 --- a/src/Bup/Bit.Bup/Scripts/bit-bup.ts +++ b/src/Bup/Bit.Bup/Scripts/bit-bup.ts @@ -1,5 +1,5 @@ var BitBup = BitBup || {}; -BitBup.version = window['bit-bup version'] = '9.2.0'; +BitBup.version = window['bit-bup version'] = '9.2.1'; declare const Blazor: any; diff --git a/src/Butil/Bit.Butil/Scripts/butil.ts b/src/Butil/Bit.Butil/Scripts/butil.ts index b1860b91da..9da10d20dd 100644 --- a/src/Butil/Bit.Butil/Scripts/butil.ts +++ b/src/Butil/Bit.Butil/Scripts/butil.ts @@ -1,2 +1,2 @@ var BitButil = BitButil || {}; -BitButil.version = window['bit-butil version'] = '9.2.0'; \ No newline at end of file +BitButil.version = window['bit-butil version'] = '9.2.1'; \ No newline at end of file diff --git a/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty.Client/BlazorEmpty.Client.csproj b/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty.Client/BlazorEmpty.Client.csproj index 4a7014cd4a..63fae6a659 100644 --- a/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty.Client/BlazorEmpty.Client.csproj +++ b/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty.Client/BlazorEmpty.Client.csproj @@ -1,4 +1,4 @@ - + @@ -17,14 +17,14 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty/BlazorEmpty.csproj b/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty/BlazorEmpty.csproj index 8f1ac9bc45..4583998bb3 100644 --- a/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty/BlazorEmpty.csproj +++ b/src/Templates/BlazorEmpty/Bit.BlazorEmpty/BlazorEmpty/BlazorEmpty.csproj @@ -1,4 +1,4 @@ - + @@ -19,14 +19,14 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangeEmailSection.razor b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangeEmailSection.razor index ef92198768..3a277f44d2 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangeEmailSection.razor +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangeEmailSection.razor @@ -10,7 +10,7 @@ @if (Email is not null) { - + } - + diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangePhoneNumberSection.razor b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangePhoneNumberSection.razor index 37f070c354..d046de2bbe 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangePhoneNumberSection.razor +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangePhoneNumberSection.razor @@ -10,7 +10,7 @@ @if (PhoneNumber is not null) { - + } - + diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Todo/TodoPage.razor b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Todo/TodoPage.razor index 89853b379c..53bc60d571 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Todo/TodoPage.razor +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Todo/TodoPage.razor @@ -26,9 +26,9 @@ - - - + + + -/// Social sign-in functions seamlessly on web browsers and on Android and iOS via universal app links. -/// However, for blazor hybrid, a local HTTP server is needed to ensure a smooth social sign-in experience. -/// public interface ILocalHttpServer { int Start(CancellationToken cancellationToken); + + /// + /// Social sign-in on the web version of the app uses simple redirects. However, for Android, iOS, Windows, and macOS, social sign-in requires an in-app or external browser. + /// + /// # Navigating Back to the App After Social Sign-In + /// 1. **Universal Deep Links**: Allow the app to directly handle specific web links (for iOS and Android apps). + /// 2. **Local HTTP Server**: Works similarly to how `git.exe` manages sign-ins with services like GitHub (supported on iOS, Android, Windows, and macOS). + /// + /// - **iOS, Windows, and macOS**: Use local HTTP server implementations in MAUI and Windows projects. + /// - **Android**: Use universal links. + /// + bool ShouldUseForSocialSignIn(); } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/NoopLocalHttpServer.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/NoopLocalHttpServer.cs index ed0060400a..faf3b701f9 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/NoopLocalHttpServer.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/NoopLocalHttpServer.cs @@ -1,10 +1,11 @@ namespace Boilerplate.Client.Core.Services; -/// -/// -/// The is specifically registered for Android, iOS, and Web, where a local HTTP server is unnecessary. -/// public partial class NoopLocalHttpServer : ILocalHttpServer { - public int Start(CancellationToken cancellationToken) => -1; + public int Start(CancellationToken cancellationToken) => throw new NotImplementedException(); + + /// + /// + /// + public bool ShouldUseForSocialSignIn() => false; } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/App.xaml.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/App.xaml.cs index b2ca0d9828..37f1f2a43b 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/App.xaml.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/App.xaml.cs @@ -4,6 +4,7 @@ using Maui.InAppReviews; using System.Runtime.InteropServices; //#endif +using Microsoft.Extensions.Logging; [assembly: XamlCompilation(XamlCompilationOptions.Compile)] @@ -15,6 +16,7 @@ public partial class App //#if (framework == 'net9.0') private readonly IStorageService storageService; //#endif + private readonly ILogger logger; private readonly IExceptionHandler exceptionHandler; private readonly IBitDeviceCoordinator deviceCoordinator; private readonly IStringLocalizer localizer; @@ -24,10 +26,12 @@ public App(MainPage mainPage, PubSubService pubSubService, IStorageService storageService, //#endif + ILogger logger, IExceptionHandler exceptionHandler, IBitDeviceCoordinator deviceCoordinator, IStringLocalizer localizer) { + this.logger = logger; this.localizer = localizer; //#if (framework == 'net9.0') this.storageService = storageService; @@ -72,11 +76,17 @@ protected override async void OnStart() //+:cnd:noEmit //#if (framework == 'net9.0') const int minimumSupportedWebViewVersion = 94; + // Download link for Android emulator (x86 or x86_64) + // https://www.apkmirror.com/apk/google-inc/chrome/chrome-94-0-4606-50-release/ + // https://www.apkmirror.com/apk/google-inc/android-system-webview/android-system-webview-94-0-4606-85-release/ //#elif (framework == 'net8.0') //#if (IsInsideProjectTemplate) /* //#endif const int minimumSupportedWebViewVersion = 84; + // Download link for Android emulator (x86 or x86_64) + // https://www.apkmirror.com/apk/google-inc/chrome/chrome-84-0-4147-89-release/ + // https://www.apkmirror.com/apk/google-inc/android-system-webview/android-system-webview-84-0-4147-111-release/ //#if (IsInsideProjectTemplate) */ //#endif @@ -85,8 +95,10 @@ protected override async void OnStart() if (Version.TryParse(Android.Webkit.WebView.CurrentWebViewPackage?.VersionName, out var webViewVersion) && webViewVersion.Major < minimumSupportedWebViewVersion) { + var webViewName = Android.Webkit.WebView.CurrentWebViewPackage.PackageName; + logger.LogWarning("{webViewName} version {version} is not supported.", webViewName, webViewVersion); await App.Current!.Windows[0].Page!.DisplayAlert("Boilerplate", localizer[nameof(AppStrings.UpdateWebViewThroughGooglePlay)], localizer[nameof(AppStrings.Ok)]); - await Launcher.OpenAsync($"https://play.google.com/store/apps/details?id={Android.Webkit.WebView.CurrentWebViewPackage.PackageName}"); + await Launcher.OpenAsync($"https://play.google.com/store/apps/details?id={webViewName}"); } //-:cnd:noEmit #endif diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/MauiProgram.Services.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/MauiProgram.Services.cs index c169776987..78ba7c58a2 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/MauiProgram.Services.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/MauiProgram.Services.cs @@ -39,12 +39,7 @@ public static void ConfigureServices(this MauiAppBuilder builder) return settings; }); services.AddSingleton(ITelemetryContext.Current!); - if (AppPlatform.IsAndroid is false) - { - // Handle social sign-in callback on local HTTP server. - // But in Android, leverage Universal Links for smoother sign-in flows. - services.AddSingleton(); - } + services.AddSingleton(); services.AddMauiBlazorWebView(); services.AddBlazorWebViewDeveloperTools(); diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/Services/MauiLocalHttpServer.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/Services/MauiLocalHttpServer.cs index d4c134d38b..64d5ed792e 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/Services/MauiLocalHttpServer.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Maui/Services/MauiLocalHttpServer.cs @@ -1,14 +1,11 @@ using EmbedIO; using System.Net; -using System.Net.Sockets; using EmbedIO.Actions; +using System.Net.Sockets; using Boilerplate.Client.Core.Components; namespace Boilerplate.Client.Maui.Services; -/// -/// -/// public partial class MauiLocalHttpServer : ILocalHttpServer { [AutoInject] private IExceptionHandler exceptionHandler; @@ -89,4 +86,12 @@ private int GetAvailableTcpPort() l.Stop(); return port; } + + /// + /// + /// + public bool ShouldUseForSocialSignIn() + { + return AppPlatform.IsAndroid is false; + } } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/service-worker.published.js b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/service-worker.published.js index 2eae8c98dd..87949e8fb4 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/service-worker.published.js +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/service-worker.published.js @@ -1,5 +1,5 @@ //+:cnd:noEmit -// bit version: 9.2.0 +// bit version: 9.2.1 // https://github.com/bitfoundation/bitplatform/tree/develop/src/Bswup //#if (notification == true) diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/staticwebapp.config.json b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/staticwebapp.config.json new file mode 100644 index 0000000000..9d62611db5 --- /dev/null +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/staticwebapp.config.json @@ -0,0 +1,5 @@ +{ + "navigationFallback": { + "rewrite": "/index.html" + } +} \ No newline at end of file diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Windows/Services/WindowsLocalHttpServer.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Windows/Services/WindowsLocalHttpServer.cs index cf52aed8b4..eec2676c23 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Windows/Services/WindowsLocalHttpServer.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Windows/Services/WindowsLocalHttpServer.cs @@ -1,6 +1,5 @@ using EmbedIO; using System.Net; -using System.Net.Http; using System.Net.Sockets; using EmbedIO.Actions; using Boilerplate.Client.Core.Components; @@ -69,6 +68,12 @@ public int Start(CancellationToken cancellationToken) return port; } + /// + /// + /// + + public bool ShouldUseForSocialSignIn() => true; + private int GetAvailableTcpPort() { using TcpListener l = new TcpListener(IPAddress.Loopback, 0); diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Build.props b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Build.props index 646c637100..8e2f14f742 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Build.props +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Build.props @@ -1,4 +1,4 @@ - + diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props index 4433670f7b..97d8cc70b1 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props @@ -1,14 +1,14 @@  - - - - - - - - + + + + + + + + @@ -49,7 +49,7 @@ - + diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props index e3994a4ec3..e40a1819f1 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props @@ -1,14 +1,14 @@  - - - - - - - - + + + + + + + + @@ -46,7 +46,7 @@ - + diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Categories/CategoryController.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Categories/CategoryController.cs index 71d60e625c..abaf6e9a4f 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Categories/CategoryController.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Categories/CategoryController.cs @@ -29,8 +29,8 @@ public async Task> GetCategories(ODataQueryOptions(await query.ToArrayAsync(cancellationToken), totalCount); } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.PhoneConfirmation.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.PhoneConfirmation.cs index 1db25ddd3d..7fe274d25a 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.PhoneConfirmation.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.PhoneConfirmation.cs @@ -78,6 +78,8 @@ private async Task SendConfirmPhoneToken(User user, CancellationToken cancellati var phoneNumber = user.PhoneNumber!; var token = await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"VerifyPhoneNumber:{phoneNumber},{user.PhoneNumberTokenRequestedOn?.ToUniversalTime()}")); - await phoneService.SendSms(Localizer[nameof(AppStrings.ConfirmPhoneTokenSmsText), token], phoneNumber, cancellationToken); + var message = Localizer[nameof(AppStrings.ConfirmPhoneTokenShortText), token]; + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; + await phoneService.SendSms(smsMessage, phoneNumber, cancellationToken); } } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.ResetPassword.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.ResetPassword.cs index 0b3614af31..34d0c9ce89 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.ResetPassword.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.ResetPassword.cs @@ -49,7 +49,8 @@ public async Task SendResetPasswordToken(SendResetPasswordTokenRequestDto reques if (await userManager.IsPhoneNumberConfirmedAsync(user)) { - sendMessagesTasks.Add(phoneService.SendSms(message, user.PhoneNumber!, cancellationToken)); + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; + sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken)); } //#if (signalR == true) diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.cs index d11bdb2eb0..3a30a9f9d9 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.cs @@ -308,7 +308,9 @@ public async Task SendOtp(IdentityRequestDto request, string? returnUrl = null, if (await userManager.IsPhoneNumberConfirmedAsync(user)) { - var smsMessage = Localizer[nameof(AppStrings.OtpShortText), await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"Otp_Sms,{user.OtpRequestedOn?.ToUniversalTime()}"))].ToString(); + var token = await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"Otp_Sms,{user.OtpRequestedOn?.ToUniversalTime()}")); + var message = Localizer[nameof(AppStrings.OtpShortText), token].ToString(); + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken)); } @@ -368,7 +370,8 @@ public async Task SendTwoFactorToken(SignInRequestDto request, CancellationToken if (firstStepAuthenticationMethod != "Sms" && await userManager.IsPhoneNumberConfirmedAsync(user)) { - sendMessagesTasks.Add(phoneService.SendSms(message, user.PhoneNumber!, cancellationToken)); + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; + sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken)); } if (firstStepAuthenticationMethod != "Push") diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/UserController.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/UserController.cs index 3db42bd079..80c83b35e6 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/UserController.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/UserController.cs @@ -228,7 +228,10 @@ public async Task SendChangePhoneNumberToken(SendPhoneTokenRequestDto request, C var token = await userManager.GenerateChangePhoneNumberTokenAsync(user!, request.PhoneNumber!); - await phoneService.SendSms(Localizer[nameof(AppStrings.ChangePhoneNumberTokenSmsText), token], request.PhoneNumber!, cancellationToken); + var message = Localizer[nameof(AppStrings.ChangePhoneNumberTokenShortText), token]; + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; + + await phoneService.SendSms(smsMessage, request.PhoneNumber!, cancellationToken); } [HttpPost] @@ -388,7 +391,7 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken) List sendMessagesTasks = []; - var messageText = Localizer[nameof(AppStrings.ElevatedAccessToken), token].ToString(); + var message = Localizer[nameof(AppStrings.ElevatedAccessTokenShortText), token].ToString(); if (await userManager.IsEmailConfirmedAsync(user)) { @@ -397,7 +400,8 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken) if (await userManager.IsPhoneNumberConfirmedAsync(user)) { - sendMessagesTasks.Add(phoneService.SendSms(messageText, user.PhoneNumber!, cancellationToken)); + var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */; + sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken)); } //#if (signalR == true) @@ -406,11 +410,11 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken) .Where(us => us.UserId == user.Id && us.Id != currentUserSessionId && us.SignalRConnectionId != null) .Select(us => us.SignalRConnectionId!) .ToArrayAsync(cancellationToken); - sendMessagesTasks.Add(appHubContext.Clients.Clients(userSessionIdsExceptCurrentUserSessionId).SendAsync(SignalREvents.SHOW_MESSAGE, messageText, cancellationToken)); + sendMessagesTasks.Add(appHubContext.Clients.Clients(userSessionIdsExceptCurrentUserSessionId).SendAsync(SignalREvents.SHOW_MESSAGE, message, cancellationToken)); //#endif //#if (notification == true) - sendMessagesTasks.Add(pushNotificationService.RequestPush(message: messageText, userRelatedPush: true, customSubscriptionFilter: us => us.UserSession!.UserId == user.Id && us.UserSessionId != currentUserSessionId, cancellationToken: cancellationToken)); + sendMessagesTasks.Add(pushNotificationService.RequestPush(message: message, userRelatedPush: true, customSubscriptionFilter: us => us.UserSession!.UserId == user.Id && us.UserSessionId != currentUserSessionId, cancellationToken: cancellationToken)); //#endif await Task.WhenAll(sendMessagesTasks); diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Products/ProductController.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Products/ProductController.cs index 0e18f16793..d2186b2863 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Products/ProductController.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Products/ProductController.cs @@ -29,8 +29,8 @@ public async Task> GetProducts(ODataQueryOptions(await query.ToArrayAsync(cancellationToken), totalCount); } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Todo/TodoItemController.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Todo/TodoItemController.cs index 975be7800f..3f3fac0d9a 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Todo/TodoItemController.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Todo/TodoItemController.cs @@ -23,8 +23,8 @@ public async Task> GetTodoItems(ODataQueryOptions(await query.ToArrayAsync(cancellationToken), totalCount); } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Extensions/LinqExtensions.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Extensions/LinqExtensions.cs index fee57093a2..c25cff974a 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Extensions/LinqExtensions.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Extensions/LinqExtensions.cs @@ -31,6 +31,16 @@ public static IQueryable TakeIf(this IQueryable query, bool predicate, return predicate ? query.Take(count) : query; } + public static IQueryable SkipIf(this IQueryable query, bool predicate, int? count) + { + return (predicate && count.HasValue) ? query.Skip(count.Value) : query; + } + + public static IQueryable TakeIf(this IQueryable query, bool predicate, int? count) + { + return (predicate && count.HasValue) ? query.Take(count.Value) : query; + } + public static IEnumerable WhereIf(this IEnumerable source, bool predicate, Func itemPredicate) { return predicate ? source.Where(itemPredicate) : source; @@ -55,4 +65,14 @@ public static IEnumerable TakeIf(this IEnumerable source, bool predicat { return predicate ? source.Take(count) : source; } + + public static IEnumerable SkipIf(this IEnumerable source, bool predicate, int? count) + { + return (predicate && count.HasValue) ? source.Skip(count.Value) : source; + } + + public static IEnumerable TakeIf(this IEnumerable source, bool predicate, int? count) + { + return (predicate && count.HasValue) ? source.Take(count.Value) : source; + } } diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx index fc3341aaee..8540c0b04c 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx @@ -933,8 +933,8 @@ لطفا کد ۶ رقمی که ارسال کردیم یا کد Authenticator app خود را وارد کنید - - توکن {0} + + {0} کد شماست در Boilerplate شما قبلا ایمیل تایید را درخواست کرده اید. دوباره امتحان کنید در {0} @@ -987,20 +987,20 @@ شما قبلا درخواست ایمیل توکن 2FA را دارید. دوباره امتحان کنید در {0} - - {0} توکن تغییر شماره تلفن شما است در Boilerplate. + + {0} کد شماست در Boilerplate - - {0} توکن تایید شماره تلفن شما است در Boilerplate. + + {0} کد شماست در Boilerplate - {0} توکن احراز هویت مرحله دو شما است در Boilerplate. + {0} کد شماست در Boilerplate - {0} پسورد یک‌بار مصرف شما است در Boilerplate. + {0} کد شماست در Boilerplate - {0} توکن تغییر رمز عبور شما است در Boilerplate. + {0} کد شماست در Boilerplate آنلاین diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.nl.resx b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.nl.resx index 7e788854da..1ccb6a40e1 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.nl.resx +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.nl.resx @@ -933,8 +933,8 @@ Voer de verhoogde toegangstoken in die we u zojuist hebben gestuurd of de code van uw authenticator-app om door te gaan. - - Token {0} + + {0} is je code in Boilerplate. Je hebt de bevestigingsmail al aangevraagd. Probeer het opnieuw in {0} @@ -987,20 +987,20 @@ Je hebt de e-mail met de 2FA-token al aangevraagd. Probeer het opnieuw in {0}. - - {0} is het token voor het wijzigen van uw telefoonnummer in Boilerplate. + + {0} is je code in Boilerplate. - - {0} is uw bevestigingstelefoonnummer token in Boilerplate. + + {0} is je code in Boilerplate. - {0} is je tweefactortoken in Boilerplate. + {0} is je code in Boilerplate. - {0} is uw OTP in Boilerplate. + {0} is je code in Boilerplate. - {0} is het token voor het opnieuw instellen van uw wachtwoord in Boilerplate. + {0} is je code in Boilerplate. Online diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx index 2073430021..ba56c544c3 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx @@ -933,8 +933,8 @@ Please enter the elevated access token we just sent you or your authenticator app code to continue. - - Token {0} + + {0} is your code in Boilerplate. You have already requested the confirmation email. Try again in {0} @@ -987,20 +987,20 @@ You have already requested the 2FA token email. Try again in {0}. - - {0} is your change phone number token in Boilerplate. + + {0} is your code in Boilerplate. - - {0} is your confirm phone number token in Boilerplate. + + {0} is your code in Boilerplate. - {0} is your two factor token in Boilerplate. + {0} is your code in Boilerplate. - {0} is your OTP in Boilerplate. + {0} is your code in Boilerplate. - {0} is your reset password token in Boilerplate. + {0} is your code in Boilerplate. Online diff --git a/src/Templates/Boilerplate/Bit.Boilerplate/src/Tests/PageTests/PageModels/Identity/SettingsPage.Account.Phone.cs b/src/Templates/Boilerplate/Bit.Boilerplate/src/Tests/PageTests/PageModels/Identity/SettingsPage.Account.Phone.cs index 8e32dec93f..799dc19994 100644 --- a/src/Templates/Boilerplate/Bit.Boilerplate/src/Tests/PageTests/PageModels/Identity/SettingsPage.Account.Phone.cs +++ b/src/Templates/Boilerplate/Bit.Boilerplate/src/Tests/PageTests/PageModels/Identity/SettingsPage.Account.Phone.cs @@ -59,7 +59,7 @@ public async Task AssertTooManyRequestsForChangePhone() public string GetPhoneToken() { - var pattern = AppStrings.ChangePhoneNumberTokenSmsText.Replace("{0}", @"\b\d{6}\b"); + var pattern = AppStrings.ChangePhoneNumberTokenShortText.Replace("{0}", @"\b\d{6}\b"); return FakePhoneService.GetLastOtpFor(newPhone, pattern); } diff --git a/src/Websites/Careers/src/Bit.Websites.Careers.Client/Bit.Websites.Careers.Client.csproj b/src/Websites/Careers/src/Bit.Websites.Careers.Client/Bit.Websites.Careers.Client.csproj index 64c1805528..b27ca5d801 100644 --- a/src/Websites/Careers/src/Bit.Websites.Careers.Client/Bit.Websites.Careers.Client.csproj +++ b/src/Websites/Careers/src/Bit.Websites.Careers.Client/Bit.Websites.Careers.Client.csproj @@ -22,15 +22,15 @@ - - + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Careers/src/Bit.Websites.Careers.Server/Bit.Websites.Careers.Server.csproj b/src/Websites/Careers/src/Bit.Websites.Careers.Server/Bit.Websites.Careers.Server.csproj index ca355227d2..672d7fd979 100644 --- a/src/Websites/Careers/src/Bit.Websites.Careers.Server/Bit.Websites.Careers.Server.csproj +++ b/src/Websites/Careers/src/Bit.Websites.Careers.Server/Bit.Websites.Careers.Server.csproj @@ -10,11 +10,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Careers/src/Bit.Websites.Careers.Shared/Bit.Websites.Careers.Shared.csproj b/src/Websites/Careers/src/Bit.Websites.Careers.Shared/Bit.Websites.Careers.Shared.csproj index cb97211a2a..408cb4413e 100644 --- a/src/Websites/Careers/src/Bit.Websites.Careers.Shared/Bit.Websites.Careers.Shared.csproj +++ b/src/Websites/Careers/src/Bit.Websites.Careers.Shared/Bit.Websites.Careers.Shared.csproj @@ -6,11 +6,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Careers/src/Directory.Build.props b/src/Websites/Careers/src/Directory.Build.props index 5c137e1ff8..9e1130b941 100644 --- a/src/Websites/Careers/src/Directory.Build.props +++ b/src/Websites/Careers/src/Directory.Build.props @@ -1,4 +1,4 @@ - + 13.0 diff --git a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Bit.Websites.Platform.Client.csproj b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Bit.Websites.Platform.Client.csproj index 442642400d..ce019045a3 100644 --- a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Bit.Websites.Platform.Client.csproj +++ b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Bit.Websites.Platform.Client.csproj @@ -22,16 +22,16 @@ - - - + + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor index d2199db6dc..fa602a5631 100644 --- a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor +++ b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor @@ -174,8 +174,8 @@ rm $HOME/dotnet.tar.gz }
  • -
    Install Bit Boilerplate project template
    - dotnet new install Bit.Boilerplate::9.2.0 +
    Install Bit Boilerplate project template
    + dotnet new install Bit.Boilerplate::9.2.1
  • @if (showCrossPlatform && devOS is "Windows") { diff --git a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor.cs b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor.cs index d8aaf79593..3946c5db6b 100644 --- a/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor.cs +++ b/src/Websites/Platform/src/Bit.Websites.Platform.Client/Pages/Templates/Templates03GettingStartedPage.razor.cs @@ -38,7 +38,7 @@ public partial class Templates03GettingStartedPage command:"dotnet nuget add source \"https://api.nuget.org/v3/index.json\" --name \"nuget.org\"; dotnet workload install wasm-tools;"), (text:@"echo 'Install the Bit.Boilerplate project template https://www.nuget.org/packages/Boilerplate.Templates';", - command:"dotnet new install Bit.Boilerplate::9.2.0;") + command:"dotnet new install Bit.Boilerplate::9.2.1;") ]; if (enableVirtualization) diff --git a/src/Websites/Platform/src/Bit.Websites.Platform.Server/Bit.Websites.Platform.Server.csproj b/src/Websites/Platform/src/Bit.Websites.Platform.Server/Bit.Websites.Platform.Server.csproj index b41138f013..08fa5c0c5e 100644 --- a/src/Websites/Platform/src/Bit.Websites.Platform.Server/Bit.Websites.Platform.Server.csproj +++ b/src/Websites/Platform/src/Bit.Websites.Platform.Server/Bit.Websites.Platform.Server.csproj @@ -10,11 +10,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Platform/src/Bit.Websites.Platform.Shared/Bit.Websites.Platform.Shared.csproj b/src/Websites/Platform/src/Bit.Websites.Platform.Shared/Bit.Websites.Platform.Shared.csproj index cb97211a2a..408cb4413e 100644 --- a/src/Websites/Platform/src/Bit.Websites.Platform.Shared/Bit.Websites.Platform.Shared.csproj +++ b/src/Websites/Platform/src/Bit.Websites.Platform.Shared/Bit.Websites.Platform.Shared.csproj @@ -6,11 +6,11 @@
    - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Platform/src/Directory.Build.props b/src/Websites/Platform/src/Directory.Build.props index 896aa49df7..6fb10075bb 100644 --- a/src/Websites/Platform/src/Directory.Build.props +++ b/src/Websites/Platform/src/Directory.Build.props @@ -1,4 +1,4 @@ - + preview diff --git a/src/Websites/Sales/src/Bit.Websites.Sales.Client/Bit.Websites.Sales.Client.csproj b/src/Websites/Sales/src/Bit.Websites.Sales.Client/Bit.Websites.Sales.Client.csproj index 4edc5892f4..a9366298a7 100644 --- a/src/Websites/Sales/src/Bit.Websites.Sales.Client/Bit.Websites.Sales.Client.csproj +++ b/src/Websites/Sales/src/Bit.Websites.Sales.Client/Bit.Websites.Sales.Client.csproj @@ -22,15 +22,15 @@ - - + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Sales/src/Bit.Websites.Sales.Server/Bit.Websites.Sales.Server.csproj b/src/Websites/Sales/src/Bit.Websites.Sales.Server/Bit.Websites.Sales.Server.csproj index 230078fd11..cf8c7f55d5 100644 --- a/src/Websites/Sales/src/Bit.Websites.Sales.Server/Bit.Websites.Sales.Server.csproj +++ b/src/Websites/Sales/src/Bit.Websites.Sales.Server/Bit.Websites.Sales.Server.csproj @@ -10,11 +10,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Sales/src/Bit.Websites.Sales.Shared/Bit.Websites.Sales.Shared.csproj b/src/Websites/Sales/src/Bit.Websites.Sales.Shared/Bit.Websites.Sales.Shared.csproj index cb97211a2a..408cb4413e 100644 --- a/src/Websites/Sales/src/Bit.Websites.Sales.Shared/Bit.Websites.Sales.Shared.csproj +++ b/src/Websites/Sales/src/Bit.Websites.Sales.Shared/Bit.Websites.Sales.Shared.csproj @@ -6,11 +6,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Websites/Sales/src/Directory.Build.props b/src/Websites/Sales/src/Directory.Build.props index a8c72eee81..91dd757221 100644 --- a/src/Websites/Sales/src/Directory.Build.props +++ b/src/Websites/Sales/src/Directory.Build.props @@ -1,4 +1,4 @@ - + 13.0