dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit a7a47a113fdfb6a44ff86e2ef897dcca4d91a576
parent ebbcb27e89a2a4eb2373000d0b60a411e0e4a170
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Thu, 28 Dec 2023 21:42:26 -0500

fix "stop tab loading icon" for new stream menu

Diffstat:
Mpkg/pubsub/pubsub.go | 28++++++++++++++++------------
Mpkg/web/handlers/api/v1/chat.go | 17++++++++++++++++-
2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/pkg/pubsub/pubsub.go b/pkg/pubsub/pubsub.go @@ -50,7 +50,7 @@ func (p *PubSub[T]) removeSubscriber(s *Sub[T]) { // Subscribe is an alias for NewSub func (p *PubSub[T]) Subscribe(topics []string) *Sub[T] { ctx, cancel := context.WithCancel(context.Background()) - s := &Sub[T]{topics: topics, ch: make(chan payload[T], 10), ctx: ctx, cancel: cancel, p: p} + s := &Sub[T]{topics: topics, ch: make(chan Payload[T], 10), ctx: ctx, cancel: cancel, p: p} p.addSubscriber(s) return s } @@ -58,14 +58,13 @@ func (p *PubSub[T]) Subscribe(topics []string) *Sub[T] { // Pub shortcut for publish which ignore the error func (p *PubSub[T]) Pub(topic string, msg T) { for _, s := range p.getSubscribers(topic) { - s.publish(payload[T]{topic, msg}) + s.publish(Payload[T]{topic, msg}) } } -// -type payload[T any] struct { - topic string - msg T +type Payload[T any] struct { + Topic string + Msg T } // ErrTimeout error returned when timeout occurs @@ -74,10 +73,10 @@ var ErrTimeout = errors.New("timeout") // ErrCancelled error returned when context is cancelled var ErrCancelled = errors.New("cancelled") -// Sub subscriber will receive messages published on a topic in his ch +// Sub subscriber will receive messages published on a Topic in his ch type Sub[T any] struct { topics []string // Topics subscribed to - ch chan payload[T] // Receives messages in this channel + ch chan Payload[T] // Receives messages in this channel ctx context.Context cancel context.CancelFunc p *PubSub[T] @@ -87,7 +86,7 @@ type Sub[T any] struct { func (s *Sub[T]) ReceiveTimeout2(timeout time.Duration, c1 <-chan struct{}) (topic string, msg T, err error) { select { case p := <-s.ch: - return p.topic, p.msg, nil + return p.Topic, p.Msg, nil case <-time.After(timeout): return topic, msg, ErrTimeout case <-c1: @@ -108,20 +107,25 @@ func (s *Sub[T]) Receive() (topic string, msg T, err error) { var res T select { case p := <-s.ch: - return p.topic, p.msg, nil + return p.Topic, p.Msg, nil case <-s.ctx.Done(): return topic, res, ErrCancelled } } -// Close will remove the subscriber from the topic subscribers +// ReceiveCh returns a message +func (s *Sub[T]) ReceiveCh() <-chan Payload[T] { + return s.ch +} + +// Close will remove the subscriber from the Topic subscribers func (s *Sub[T]) Close() { s.cancel() s.p.removeSubscriber(s) } // publish a message to the subscriber channel -func (s *Sub[T]) publish(p payload[T]) { +func (s *Sub[T]) publish(p Payload[T]) { select { case s.ch <- p: default: diff --git a/pkg/web/handlers/api/v1/chat.go b/pkg/web/handlers/api/v1/chat.go @@ -178,12 +178,14 @@ func ChatStreamMessagesHandler(c echo.Context) error { c.Response().Flush() // Create a subscriber and topics to listen to + selfRefreshLoadingIconTopic := "refresh_loading_icon_" + string(authUser.Username) selfRefreshTopic := "refresh_" + string(authUser.Username) selfWizzTopic := "wizz_" + string(authUser.Username) readMarkerTopic := "readmarker_" + authUser.ID.String() authorizedTopics := []string{ database.RefreshTopic, selfRefreshTopic, + selfRefreshLoadingIconTopic, selfWizzTopic, readMarkerTopic, "room_" + room.ID.String()} @@ -283,6 +285,11 @@ Loop: continue } + if topic == selfRefreshLoadingIconTopic { + send(`<meta http-equiv="refresh" content="1" />`) + return nil + } + if topic == selfRefreshTopic || msgTyp.Typ == database.ForceRefresh { send(metaRefresh) return nil @@ -430,10 +437,14 @@ func ChatStreamMenuHandler(c echo.Context) error { hutils.SetStreamingHeaders(c) quit := hutils.CloseSignalChan(c) send := func(s string) { _, _ = c.Response().Write([]byte(s)) } + selfRefreshTopic := "refresh_loading_icon_" + string(authUser.Username) var prevHash string var menuID int var once utils.Once + sub := database.MsgPubSub.Subscribe([]string{selfRefreshTopic}) + defer sub.Close() + send(GenerateStyle(authUser, ChatMessagesData{})) Loop: @@ -441,9 +452,13 @@ Loop: select { case <-once.After(0 * time.Millisecond): case <-time.After(5 * time.Second): + case <-sub.ReceiveCh(): + send(`<meta http-equiv="refresh" content="1" />`) + return nil case <-quit: break Loop } + data := GetChatMenuData(c, room) rightColumn := RenderRightColumn(authUser, data) newHash := utils.MD5([]byte(rightColumn)) @@ -461,6 +476,6 @@ Loop: func ChatStreamMessagesRefreshHandler(c echo.Context) error { authUser := c.Get("authUser").(*database.User) - database.MsgPubSub.Pub("refresh_"+string(authUser.Username), database.ChatMessageType{Typ: database.ForceRefresh}) + database.MsgPubSub.Pub("refresh_loading_icon_"+string(authUser.Username), database.ChatMessageType{Typ: database.ForceRefresh}) return c.NoContent(http.StatusOK) }