Skip to content

Conversation

@ArgoZhang
Copy link
Member

@ArgoZhang ArgoZhang commented Feb 12, 2026

Link issues

fixes #7659

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Allow FlipClock to be reset with an explicit start time instead of relying on a nullable StartValue property.

New Features:

  • Add an overloadable Reset method on FlipClock that accepts an optional TimeSpan value to control the reset start time.

Enhancements:

  • Make FlipClock StartValue non-nullable and initialize via the Reset method during component initialization.

Tests:

  • Update FlipClock unit test to use the new Reset API instead of setting StartValue to null.

Copilot AI review requested due to automatic review settings February 12, 2026 06:01
@bb-auto bb-auto bot added the bug Something isn't working label Feb 12, 2026
@bb-auto bb-auto bot added this to the v10.3.0 milestone Feb 12, 2026
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 12, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Introduces a value parameterized Reset method for FlipClock, makes StartValue non-nullable, wires initialization to use the new API, and updates the unit test to use the new Reset behavior instead of rebinding a nullable StartValue.

Sequence diagram for FlipClock initialization using parameterized Reset

sequenceDiagram
participant BlazorRuntime
participant FlipClock
participant JSRuntime

BlazorRuntime->>FlipClock: InvokeInitAsync()
activate FlipClock
FlipClock->>FlipClock: Reset(StartValue)
FlipClock->>JSRuntime: InvokeVoidAsync(init, Id, Interop, options)
activate JSRuntime
JSRuntime-->>FlipClock: Task completed
deactivate JSRuntime
FlipClock-->>BlazorRuntime: Task completed
deactivate FlipClock
Loading

Class diagram for updated FlipClock Reset API

classDiagram
class ComponentBase

class FlipClock {
  +TimeSpan StartValue
  +Task InvokeInitAsync()
  +Task Reset(TimeSpan? value)
}

FlipClock --|> ComponentBase
Loading

File-Level Changes

Change Details Files
Refactor FlipClock initialization/reset flow to use a parameterized Reset(TimeSpan?) and make StartValue non-nullable.
  • Change StartValue from nullable TimeSpan? to non-nullable TimeSpan and remove null-handling helper GetTicks
  • Update InvokeInitAsync lifecycle hook to call Reset(StartValue) instead of the parameterless Reset
  • Redesign Reset to accept an optional TimeSpan? value, defaulting null to TimeSpan.Zero, and pass its TotalMilliseconds to the JS init interop payload
src/BootstrapBlazor/Components/FlipClock/FlipClock.razor.cs
Align unit tests with the new Reset API and non-nullable StartValue behavior.
  • Update ViewMode_Ok test to invoke Reset via the component instance rather than re-rendering with a null StartValue
test/UnitTest/Components/FlipClockTest.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#7659 Provide a callable Reset method for the FlipClock component that resets the clock via JS interop.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The new Reset(TimeSpan? value = null) overload no longer uses the StartValue property when called without arguments (unlike the previous Reset() behavior), which may surprise callers expecting a reset to honor the configured start value; consider defaulting to StartValue when value is null rather than TimeSpan.Zero.
  • Changing StartValue from TimeSpan? to non-nullable TimeSpan is a public API change that can break existing usages that bind or assign null; if backward compatibility is important, consider keeping it nullable and handling null internally instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `Reset(TimeSpan? value = null)` overload no longer uses the `StartValue` property when called without arguments (unlike the previous `Reset()` behavior), which may surprise callers expecting a reset to honor the configured start value; consider defaulting to `StartValue` when `value` is `null` rather than `TimeSpan.Zero`.
- Changing `StartValue` from `TimeSpan?` to non-nullable `TimeSpan` is a public API change that can break existing usages that bind or assign `null`; if backward compatibility is important, consider keeping it nullable and handling `null` internally instead.

## Individual Comments

### Comment 1
<location> `src/BootstrapBlazor/Components/FlipClock/FlipClock.razor.cs:154` </location>
<code_context>
     /// </summary>
     [Parameter]
-    public TimeSpan? StartValue { get; set; }
+    public TimeSpan StartValue { get; set; }

     private string? ClassString => CssBuilder.Default("bb-flip-clock")
</code_context>

<issue_to_address>
**suggestion:** Consider aligning the parameter nullability with how `Reset` is now using `StartValue`.

Since `StartValue` is now non-nullable and defaults to `TimeSpan.Zero`, you can simplify `Reset` by making its parameter non-nullable as well (e.g. `public Task Reset(TimeSpan value = default)` and `InvokeInitAsync() => Reset(StartValue)`). This keeps the concept consistently non-nullable and removes the need for null handling.

Suggested implementation:

```csharp
    /// <para lang="en">Gets or sets Start Time for Countdown or Count <see cref="FlipClockViewMode.Count"/> Default Effective in <see cref="FlipClockViewMode.CountDown" /> Mode</para>
    /// </summary>
    [Parameter]
    public TimeSpan StartValue { get; set; }

    private string? ClassString => CssBuilder.Default("bb-flip-clock")
        .AddClassFromAttributes(AdditionalAttributes)
    /// <summary>
    /// <inheritdoc/>
    /// </summary>
    protected override Task InvokeInitAsync() => Reset(StartValue);

```

```csharp
    public Task Reset(TimeSpan value = default)

```

Because `value` is now non-nullable, any null-handling in the `Reset` body that relies on `TimeSpan?` (for example: `value ??= StartValue;`, `var start = value ?? StartValue;`, or similar patterns) should be simplified to use `value` directly, e.g.:
- Replace `value ??= StartValue;` with `if (value == default) value = StartValue;` if you still want to treat `default` as “use StartValue”.
- Replace `var start = value ?? StartValue;` with `var start = value;` if the caller always passes the effective start value.
Please adjust these inside `Reset` according to the exact semantics you want between `default` and `StartValue`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

/// </summary>
[Parameter]
public TimeSpan? StartValue { get; set; }
public TimeSpan StartValue { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider aligning the parameter nullability with how Reset is now using StartValue.

Since StartValue is now non-nullable and defaults to TimeSpan.Zero, you can simplify Reset by making its parameter non-nullable as well (e.g. public Task Reset(TimeSpan value = default) and InvokeInitAsync() => Reset(StartValue)). This keeps the concept consistently non-nullable and removes the need for null handling.

Suggested implementation:

    /// <para lang="en">Gets or sets Start Time for Countdown or Count <see cref="FlipClockViewMode.Count"/> Default Effective in <see cref="FlipClockViewMode.CountDown" /> Mode</para>
    /// </summary>
    [Parameter]
    public TimeSpan StartValue { get; set; }

    private string? ClassString => CssBuilder.Default("bb-flip-clock")
        .AddClassFromAttributes(AdditionalAttributes)
    /// <summary>
    /// <inheritdoc/>
    /// </summary>
    protected override Task InvokeInitAsync() => Reset(StartValue);
    public Task Reset(TimeSpan value = default)

Because value is now non-nullable, any null-handling in the Reset body that relies on TimeSpan? (for example: value ??= StartValue;, var start = value ?? StartValue;, or similar patterns) should be simplified to use value directly, e.g.:

  • Replace value ??= StartValue; with if (value == default) value = StartValue; if you still want to treat default as “use StartValue”.
  • Replace var start = value ?? StartValue; with var start = value; if the caller always passes the effective start value.
    Please adjust these inside Reset according to the exact semantics you want between default and StartValue.

@codecov
Copy link

codecov bot commented Feb 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (d49a9e8) to head (c2c57ad).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #7662   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          749       749           
  Lines        33183     33188    +5     
  Branches      4604      4604           
=========================================
+ Hits         33183     33188    +5     
Flag Coverage Δ
BB 100.00% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ArgoZhang ArgoZhang merged commit 0947e68 into main Feb 12, 2026
6 checks passed
@ArgoZhang ArgoZhang deleted the refactor-flip branch February 12, 2026 06:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a value argument to the FlipClock.Reset API so callers can re-initialize the clock with a specific start value, and updates initialization/tests accordingly.

Changes:

  • Update FlipClock.Reset to accept an optional TimeSpan? value and pass it to JS init.
  • Change StartValue parameter from TimeSpan? to TimeSpan and initialize via Reset(StartValue).
  • Adjust FlipClockTest to call Reset() directly.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
test/UnitTest/Components/FlipClockTest.cs Updates the unit test to call the new/updated Reset() method.
src/BootstrapBlazor/Components/FlipClock/FlipClock.razor.cs Modifies the component API (StartValue nullability, Reset(value)), and adjusts initialization to use StartValue.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/// </summary>
[Parameter]
public TimeSpan? StartValue { get; set; }
public TimeSpan StartValue { get; set; }
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing StartValue from TimeSpan? to non-nullable TimeSpan is a breaking public API change for consumers that previously bound a nullable value (or explicitly passed null). If the goal is just to ensure a default of zero, consider keeping the parameter nullable and treating null as TimeSpan.Zero internally, or introduce a new non-nullable parameter while keeping the old one for backward compatibility.

Suggested change
public TimeSpan StartValue { get; set; }
public TimeSpan? StartValue { get; set; }

Copilot uses AI. Check for mistakes.
Comment on lines +187 to +195
if (value == null)
{
value = TimeSpan.Zero;
}
return InvokeVoidAsync("init", Id, Interop, new
{
OnCompleted = nameof(OnCompleted),
ViewMode = ViewMode.ToString(),
StartValue = value.Value.TotalMilliseconds
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reset(TimeSpan? value = null) currently treats a null argument as TimeSpan.Zero. This changes the previous behavior where calling Reset() would reset to the component's configured StartValue (or zero if it wasn't set). To preserve expected semantics, default the reset value to StartValue (and only fall back to zero when both are unset), or provide an overload pair like Reset() and Reset(TimeSpan value) instead of using a nullable optional parameter.

Suggested change
if (value == null)
{
value = TimeSpan.Zero;
}
return InvokeVoidAsync("init", Id, Interop, new
{
OnCompleted = nameof(OnCompleted),
ViewMode = ViewMode.ToString(),
StartValue = value.Value.TotalMilliseconds
var start = value ?? StartValue ?? TimeSpan.Zero;
return InvokeVoidAsync("init", Id, Interop, new
{
OnCompleted = nameof(OnCompleted),
ViewMode = ViewMode.ToString(),
StartValue = start.TotalMilliseconds

Copilot uses AI. Check for mistakes.
{
pb.Add(a => a.StartValue, null);
});
await cut.InvokeAsync(() => cut.Instance.Reset());
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test now calls Reset() but doesn't assert anything about the new behavior (e.g., that the JS init is invoked with the expected start value, or that Reset() respects the component's configured StartValue). Since this PR introduces a new Reset(value) path, consider adding an assertion (via bUnit JSInterop setup/verification) that the correct startValue is sent for both Reset() and Reset(TimeSpan).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FlipClock 中找不到 Reset方法

1 participant