1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-28 13:18:37 +00:00

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

This PR fixes a state de-synchronization bug with the issue stopwatch,
it 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.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Junsik Kong
2025-06-25 08:22:58 +09:00
committed by GitHub
parent 63fb25382b
commit 0e629c545a
13 changed files with 162 additions and 204 deletions

View File

@@ -10,33 +10,47 @@ import (
"code.gitea.io/gitea/services/context"
)
// IssueStopwatch creates or stops a stopwatch for the given issue.
func IssueStopwatch(c *context.Context) {
// IssueStartStopwatch creates a stopwatch for the given issue.
func IssueStartStopwatch(c *context.Context) {
issue := GetActionIssue(c)
if c.Written() {
return
}
var showSuccessMessage bool
if !issues_model.StopwatchExists(c, c.Doer.ID, issue.ID) {
showSuccessMessage = true
}
if !c.Repo.CanUseTimetracker(c, issue, c.Doer) {
c.NotFound(nil)
return
}
if err := issues_model.CreateOrStopIssueStopwatch(c, c.Doer, issue); err != nil {
c.ServerError("CreateOrStopIssueStopwatch", err)
if ok, err := issues_model.CreateIssueStopwatch(c, c.Doer, issue); err != nil {
c.ServerError("CreateIssueStopwatch", err)
return
} else if !ok {
c.Flash.Warning(c.Tr("repo.issues.stopwatch_already_created"))
} else {
c.Flash.Success(c.Tr("repo.issues.tracker_auto_close"))
}
c.JSONRedirect("")
}
// IssueStopStopwatch stops a stopwatch for the given issue.
func IssueStopStopwatch(c *context.Context) {
issue := GetActionIssue(c)
if c.Written() {
return
}
if showSuccessMessage {
c.Flash.Success(c.Tr("repo.issues.tracker_auto_close"))
if !c.Repo.CanUseTimetracker(c, issue, c.Doer) {
c.NotFound(nil)
return
}
if ok, err := issues_model.FinishIssueStopwatch(c, c.Doer, issue); err != nil {
c.ServerError("FinishIssueStopwatch", err)
return
} else if !ok {
c.Flash.Warning(c.Tr("repo.issues.stopwatch_already_stopped"))
}
c.JSONRedirect("")
}
@@ -51,7 +65,7 @@ func CancelStopwatch(c *context.Context) {
return
}
if err := issues_model.CancelStopwatch(c, c.Doer, issue); err != nil {
if _, err := issues_model.CancelStopwatch(c, c.Doer, issue); err != nil {
c.ServerError("CancelStopwatch", err)
return
}

View File

@@ -1258,13 +1258,8 @@ func CancelAutoMergePullRequest(ctx *context.Context) {
}
func stopTimerIfAvailable(ctx *context.Context, user *user_model.User, issue *issues_model.Issue) error {
if issues_model.StopwatchExists(ctx, user.ID, issue.ID) {
if err := issues_model.CreateOrStopIssueStopwatch(ctx, user, issue); err != nil {
return err
}
}
return nil
_, err := issues_model.FinishIssueStopwatch(ctx, user, issue)
return err
}
func PullsNewRedirect(ctx *context.Context) {