diff --git a/conference_ops.go b/conference_ops.go index 70ea838..67252df 100644 --- a/conference_ops.go +++ b/conference_ops.go @@ -184,6 +184,24 @@ func SetPseud(ctxt ui.AmContext) (string, any, error) { return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil } +/* ConfFixseen marks all messages in a conference as read. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + * Standard Go error status. + */ +func ConfFixseen(ctxt ui.AmContext) (string, any, error) { + comm := ctxt.CurrentCommunity() + conf := ctxt.GetScratch("currentConference").(*database.Conference) + err := conf.Fixseen(ctxt.Ctx(), ctxt.CurrentUser()) + if err != nil { + return ui.ErrorPage(ctxt, err) + } + return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil +} + /* AddToHotlist adds the current community and conference to the user's hotlist.. * Parameters: * ctxt - The AmContext for the request. diff --git a/database/conference.go b/database/conference.go index fa228b6..6ce1ac3 100644 --- a/database/conference.go +++ b/database/conference.go @@ -347,6 +347,71 @@ func (c *Conference) UnreadMessages(ctx context.Context, u *User) (int32, error) return rc, err } +// fixseenData is a temporary structure used in assisting with Fixseen. +type fixseenData struct { + topicid int32 + topmessage int32 + insert bool +} + +// Fixseen marks all messages in a conference as read. +func (c *Conference) Fixseen(ctx context.Context, u *User) error { + if u.IsAnon { + return nil + } + success := false + tx := amdb.MustBegin() + defer func() { + if !success { + tx.Rollback() + } + }() + + // Get a count of topics beforehand. + row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM topics WHERE confid = ?", c.ConfId) + count := 0 + err := row.Scan(&count) + if err != nil { + return err + } + + // Build the list of all topics. + rs, err := tx.QueryContext(ctx, `SELECT t.topicid, t.top_message, ISNULL(s.last_message) FROM topics t + LEFT JOIN topicsettings s ON t.topicid = s.topicid AND s.uid = ? WHERE t.confid = ?`, u.Uid, c.ConfId) + if err != nil { + return err + } + work := make([]fixseenData, 0, count) + for rs.Next() { + var d fixseenData + err = rs.Scan(&(d.topicid), &(d.topmessage), &(d.insert)) + work = append(work, d) + } + + // Adjust each topic in turn. + for _, d := range work { + if d.insert { + _, err = tx.ExecContext(ctx, "INSERT INTO topicsettings (topicid, uid, last_message, last_read) VALUES (?, ?, ?, NOW())", d.topicid, u.Uid, d.topmessage) + } else { + _, err = tx.ExecContext(ctx, "UPDATE topicsettings SET last_message = ?, last_read = NOW() WHERE topicid = ? AND uid = ?", d.topmessage, d.topicid, u.Uid) + } + if err != nil { + return err + } + } + + // Also update last-read in conference. + if _, err = c.TouchRead(ctx, tx, u); err != nil { + return err + } + + if err = tx.Commit(); err != nil { + return err + } + success = true + return nil +} + /* AmGetConference returns a conference given its ID. * Parameters: * ctx - Standard Go context value. diff --git a/database/post.go b/database/post.go index 50c8277..4e5aa53 100644 --- a/database/post.go +++ b/database/post.go @@ -284,14 +284,6 @@ func (p *PostHeader) Scribble(ctx context.Context, u *User, ipaddr string) error tx.Rollback() } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postpublish WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() - // Scribble on the post header. scribblePseud := "(Scribbled)" // FUTURE: configurable option _, err := tx.ExecContext(ctx, "UPDATE posts SET linecount = 0, hidden = 0, scribble_uid = ?, scribble_date = NOW(), pseud = ? WHERE postid = ?", u.Uid, scribblePseud, p.PostId) @@ -318,9 +310,6 @@ func (p *PostHeader) Scribble(ctx context.Context, u *User, ipaddr string) error return err } - // Unlock tables and commit. - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false if err = tx.Commit(); err != nil { return err } @@ -353,13 +342,6 @@ func (p *PostHeader) Nuke(ctx context.Context, u *User, ipaddr string) error { tx.Rollback() } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postdogear WRITE, postpublish WRITE, topics WRITE, topicsettings WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() // Delete all the references to this post. _, err := tx.ExecContext(ctx, "DELETE FROM posts WHERE postid = ?", p.PostId) @@ -399,9 +381,6 @@ func (p *PostHeader) Nuke(ctx context.Context, u *User, ipaddr string) error { return err } - // Unlock tables and commit. - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false if err = tx.Commit(); err != nil { return err } @@ -486,13 +465,6 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, ipaddr tx.Rollback() } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, posts WRITE, topicsettings WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() // Adjust post record in the database to make it part of the new topic. _, err = tx.ExecContext(ctx, "UPDATE posts SET parent = 0, topicid = ?, num = ? WHERE postid = ?", target.TopicId, target.TopMessage+1, p.PostId) @@ -534,9 +506,6 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, ipaddr return err } - // Unlock tables and commit. - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false if err = tx.Commit(); err != nil { return err } @@ -625,13 +594,6 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, tx.Rollback() } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() // Add the post header information. rs, err := tx.ExecContext(ctx, "INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (?, ?, ?, ?, NOW(), ?)", @@ -671,9 +633,6 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, topic.TopMessage = hdr.Num topic.LastUpdate = hdr.Posted - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false - // update the "last update" date of the conference and the "last posted" date in the conference settings if err = conf.TouchUpdate(ctx, tx, hdr.Posted); err != nil { return nil, err diff --git a/database/topic.go b/database/topic.go index 5dc88d5..d1ced63 100644 --- a/database/topic.go +++ b/database/topic.go @@ -349,14 +349,6 @@ func (t *Topic) Delete(ctx context.Context, u *User, ipaddr string, background * } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, topicbozo WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() - conf, err := AmGetConference(ctx, t.ConfId) if err != nil { return err @@ -373,12 +365,9 @@ func (t *Topic) Delete(ctx context.Context, u *User, ipaddr string, background * return err } - err = conf.TouchUpdate(ctx, tx, time.Now()) - if err != nil { + if err = conf.TouchUpdate(ctx, tx, time.Now()); err != nil { return err } - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false if err = tx.Commit(); err != nil { return err } @@ -670,14 +659,6 @@ func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string, } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() - // Insert the new topic into the database. conf.Mutex.Lock() rs, err := tx.ExecContext(ctx, "INSERT INTO topics (confid, num, creator_uid, createdate, lastupdate, name) VALUES (?, ?, ?, NOW(), NOW(), ?)", @@ -732,9 +713,6 @@ func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string, return nil, err } - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false - // update the "last posted" date in the conference settings _, err = conf.TouchPost(ctx, tx, user, topic.CreateDate) if err != nil { diff --git a/database/user.go b/database/user.go index 78d780a..d6efe74 100644 --- a/database/user.go +++ b/database/user.go @@ -694,13 +694,6 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi tx.Rollback() } }() - unlock := true - tx.ExecContext(ctx, "LOCK TABLES users WRITE, userprefs WRITE, propuser WRITE, commmember WRITE, sideboxes WRITE, confhotlist WRITE;") - defer func() { - if unlock { - tx.ExecContext(ctx, "UNLOCK TABLES;") - } - }() // Test if the user name is already taken. row := tx.QueryRowContext(ctx, "SELECT uid FROM users WHERE username = ?", username) @@ -749,9 +742,6 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi return nil, err } - tx.ExecContext(ctx, "UNLOCK TABLES;") - unlock = false - if err = tx.Commit(); err != nil { return nil, err } diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index 81614f5..733079e 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -54,7 +54,7 @@ _(italicized items can be deferred)_ - Find - Manage: - ~~Set pseud~~ - - Fixseen + - ~~Fixseen~~ - ~~Send invite~~ - Change information - Manage aliases diff --git a/main.go b/main.go index 1c62441..a30306f 100644 --- a/main.go +++ b/main.go @@ -105,6 +105,7 @@ func setupEcho() *echo.Echo { confGroup.POST("/new_topic", ui.AmWrap(NewTopic)) confGroup.GET("/manage", ui.AmWrap(ConfManage)) confGroup.POST("/pseud", ui.AmWrap(SetPseud)) + confGroup.GET("/fixseen", ui.AmWrap(ConfFixseen)) confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist)) confGroup.GET("/invite", ui.AmWrap(InviteToConference)) confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic) diff --git a/ui/views/manage_conf.jet b/ui/views/manage_conf.jet index 184455d..74a9f13 100644 --- a/ui/views/manage_conf.jet +++ b/ui/views/manage_conf.jet @@ -32,7 +32,7 @@
- Mark entire conference as read (fixseen) + Mark entire conference as read (fixseen)
{{ if canInvite }}