Skip to content

Conversation

jskong1124
Copy link
Contributor

@jskong1124 jskong1124 commented Jun 23, 2025

This PR fixes a state desynchronization bug with the issue stopwatch.

Problem

The current stopwatch operates on a toggle mechanism. This leads to incorrect behavior when a user interacts with stopwatches for different issues across multiple browser tabs.

Steps to reproduce:

  1. Open Issue A in Tab 1 and start the timer. The UI correctly shows a "Stop" button.
  2. Open Issue B in Tab 2 and start the timer. The server correctly stops the timer for Issue A and starts it for Issue B.
  3. Return to Tab 1. The UI still shows a "Stop" button for Issue A, even though its timer is already stopped on the server.
  4. Clicking this "Stop" button sends a toggle request, which the server interprets as a "Start" command, causing the timer to start again unexpectedly.

Solution

This PR resolves the issue by replacing the ambiguous /toggle endpoint with two explicit endpoints: /start and /stop.

  • The "Start timer" button now exclusively calls the /start endpoint.
  • The "Stop timer" button now exclusively calls the /stop endpoint.

This ensures the user's intent is clearly communicated to the server, eliminating the state inconsistency and fixing the bug.

Before (Bug in action)

before

After (Fix applied)

after

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jun 23, 2025
@github-actions github-actions bot added modifies/translation modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files labels Jun 23, 2025
@jskong1124 jskong1124 changed the title Signed-off-by: workjs1124 <kongjs123@gmail.com> fix(issue): Replace stopwatch toggle with explicit start/stop actions Jun 23, 2025
@silverwind
Copy link
Member

Good change. Please also update the integration tests:

--- FAIL: TestViewTimetrackingControls (0.92s)
    --- FAIL: TestViewTimetrackingControls/Exist (0.19s)
        testlogger.go:61: 2025/06/23 07:21:55 HTTPRequest [I] router: completed GET /user/login for test-mock:12345, 200 OK in 7.3ms @ auth/auth.go:184(auth.SignIn)
        testlogger.go:61: 2025/06/23 07:21:56 HTTPRequest [I] router: completed POST /user/login for test-mock:12345, 303 See Other in 9.1ms @ auth/auth.go:197(auth.SignInPost)
        testlogger.go:61: 2025/06/23 07:21:56 HTTPRequest [I] router: completed GET /user2/repo1/issues/1 for test-mock:12345, 200 OK in 152.1ms @ repo/issue_view.go:317(repo.ViewIssue)
        testlogger.go:61: 2025/06/23 07:21:56 HTTPRequest [I] router: completed POST /user2/repo1/issues/1/times/stopwatch/toggle for test-mock:12345, 404 Not Found in 2.0ms @ <autogenerated>:1(WebNotFound)
        timetracking_test.go:53: Response:  Not found.
            
        timetracking_test.go:53: 
            	Error Trace:	/home/runner/work/gitea/gitea/tests/integration/integration_test.go:351

@jskong1124 jskong1124 force-pushed the fix-stopwatch-toggle-bug branch from d378580 to f797f67 Compare June 23, 2025 16:59
@jskong1124
Copy link
Contributor Author

Yep! I've updated the integration tests and pushed again

@jskong1124 jskong1124 force-pushed the fix-stopwatch-toggle-bug branch from f797f67 to 3fff19d Compare June 23, 2025 17:09
@lunny lunny added this to the 1.25.0 milestone Jun 23, 2025
@lunny
Copy link
Member

lunny commented Jun 23, 2025

image
It's still using toggle on the right top bar.

fix(issue): Replace stopwatch toggle with explicit start/stop actions

The stopwatch toggle mechanism caused state desynchronization issues
when used across multiple browser tabs, leading to a "stop" action
incorrectly starting the timer again.

This commit replaces the single toggle endpoint with two explicit
endpoints: `/start` and `/stop`. This ensures that the user's
intent is always clear and prevents unexpected behavior, resolving
the state inconsistency bug.
@jskong1124
Copy link
Contributor Author

Thanks! missed that part. fixed it and pushed the update.

@GiteaBot GiteaBot added lgtm/need 1 This PR needs approval from one additional maintainer to be merged. and removed lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. labels Jun 24, 2025
@github-actions github-actions bot added the modifies/api This PR adds API routes or modifies them label Jun 24, 2025
@wxiaoguang
Copy link
Contributor

wxiaoguang commented Jun 24, 2025

Thank you for the PR. It's great to split the "toggle" to "start/stop".

When I was reviewing the code, I found another strange behavior: "start(create)" will always stop the existing stopwatch. It would cause problem when users open 2 pages for the same issue, and they have 2 "start timer" buttons.

Then I started to fix the problem, then I found more problems in legacy code .... so my commits contain more changes than I thought ...... I also added more tests to clarify these functions' behaviors.

Do the new changes look good to you?

@jskong1124
Copy link
Contributor Author

Wow, thanks so much for the detailed refactoring, @wxiaoguang. This was a great learning experience for me!
I hadn't even thought about the edge case of starting a timer on the same issue from different pages. Your approach makes a lot of sense, and I learned a lot from how you tackled it.
image

The changes look solid. LGTM!

@GiteaBot GiteaBot added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Jun 24, 2025
@lunny lunny added the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Jun 24, 2025
@wxiaoguang wxiaoguang merged commit 0e629c5 into go-gitea:main Jun 24, 2025
26 checks passed
@GiteaBot GiteaBot removed the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Jun 24, 2025
zjjhot added a commit to zjjhot/gitea that referenced this pull request Jun 26, 2025
* giteaofficial/main:
  [skip ci] Updated translations via Crowdin
  Add issue delete notifier (go-gitea#34592)
  Refactor "change file" API (go-gitea#34855)
  Fix some log and UI problems (go-gitea#34863)
  Update go tool dependencies (go-gitea#34845)
  Fix archive API (go-gitea#34853)
  Update `uint8-to-base64`, remove type stub (go-gitea#34844)
  Refactor repo contents API and add "contents-ext" API (go-gitea#34822)
  [skip ci] Updated translations via Crowdin
  fix(issue): Replace stopwatch toggle with explicit start/stop actions (go-gitea#34818)
  Remove unused variable HUGO_VERSION (go-gitea#34840)
  Fix SSH LFS timeout (go-gitea#34838)
  Ignore force pushes for changed files in a PR review (go-gitea#34837)
  Fix log fmt (go-gitea#34810)
  Fix team permissions (go-gitea#34827)
  Fix job status aggregation logic (go-gitea#34823)
  [skip ci] Updated translations via Crowdin
  correct migration tab name (go-gitea#34826)
  Refactor template helper (go-gitea#34819)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. modifies/api This PR adds API routes or modifies them modifies/frontend modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files modifies/translation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants