mirror of https://gitlab.com/ngerakines/tavern.git
190 lines
3.8 KiB
Go
190 lines
3.8 KiB
Go
package web
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/gofrs/uuid"
|
|
|
|
"github.com/ngerakines/tavern/storage"
|
|
)
|
|
|
|
type viewObjectSorter struct {
|
|
viewObjects []*viewObject
|
|
by func(v1, v2 *viewObject) bool
|
|
}
|
|
|
|
func (s *viewObjectSorter) Len() int {
|
|
return len(s.viewObjects)
|
|
}
|
|
|
|
func (s *viewObjectSorter) Swap(i, j int) {
|
|
s.viewObjects[i], s.viewObjects[j] = s.viewObjects[j], s.viewObjects[i]
|
|
}
|
|
|
|
func (s *viewObjectSorter) Less(i, j int) bool {
|
|
return s.by(s.viewObjects[i], s.viewObjects[j])
|
|
}
|
|
|
|
type viewObject struct {
|
|
ObjectRowID uuid.UUID
|
|
Raw storage.Payload
|
|
|
|
ViewContext *viewObjectContext
|
|
|
|
Parent *viewObject
|
|
Children []*viewObject
|
|
}
|
|
|
|
type viewObjectContext struct {
|
|
Focus bool
|
|
Public bool
|
|
|
|
ObjectID string
|
|
Icon string
|
|
|
|
LinkView bool
|
|
LinkViewURL string
|
|
|
|
LinkReply bool
|
|
LinkReplyURL string
|
|
|
|
LinkAnnounce bool
|
|
LinkLike bool
|
|
LinkDelete bool
|
|
|
|
AttributedTo string
|
|
AttributedToLink string
|
|
|
|
HasParent bool
|
|
ParentAttributedTo string
|
|
ParentAttributedToLink string
|
|
ParentObjectLink string
|
|
|
|
HasAnnouncer bool
|
|
AnnounceActivityID string
|
|
Announcer string
|
|
AnnouncerLink string
|
|
|
|
HasAnnouncers bool
|
|
Announcers map[string]string
|
|
|
|
Content string
|
|
|
|
HasPublishedAt bool
|
|
PublishedAt time.Time
|
|
|
|
Tags []string
|
|
Mentions []string
|
|
|
|
Media []viewContentAttachment
|
|
|
|
ViewerAnnounced bool
|
|
TotalAnnounces int
|
|
TotalReplies int
|
|
TotalLikes int
|
|
|
|
Error string
|
|
|
|
Tombstone bool
|
|
TombstoneFormerType string
|
|
TombstoneHasDeletedAt bool
|
|
TombstoneDeletedAt time.Time
|
|
|
|
Sensitive bool
|
|
ContentWarning string
|
|
|
|
ShortHash string
|
|
}
|
|
|
|
type viewContentAttachment struct {
|
|
Thumbnail string
|
|
URL string
|
|
}
|
|
|
|
type viewObjectMapper func(uuid.UUID, storage.Payload, *viewObjectContext) *viewObjectContext
|
|
|
|
func addViewObject(root *viewObject, parentObjectRowID, objectRowID uuid.UUID, payload storage.Payload) *viewObject {
|
|
if root != nil {
|
|
parent := root.searchObjectRowID(parentObjectRowID)
|
|
if parent != nil {
|
|
parent.addChild(objectRowID, payload)
|
|
return root
|
|
}
|
|
}
|
|
|
|
newRoot := createViewObject(objectRowID, payload, nil)
|
|
if root != nil {
|
|
newRoot.Children = append(newRoot.Children, root)
|
|
}
|
|
return newRoot
|
|
}
|
|
|
|
func (v *viewObject) populate(depth int, allChildren map[uuid.UUID][]uuid.UUID, refs map[uuid.UUID]storage.Payload) {
|
|
if depth > 100 {
|
|
return
|
|
}
|
|
childRowIDs, hasChildRowIDs := allChildren[v.ObjectRowID]
|
|
if !hasChildRowIDs {
|
|
return
|
|
}
|
|
for _, childRowID := range childRowIDs {
|
|
payload, hasPayload := refs[childRowID]
|
|
if !hasPayload {
|
|
continue
|
|
}
|
|
v.addChild(childRowID, payload)
|
|
}
|
|
|
|
for _, child := range v.Children {
|
|
child.populate(depth+1, allChildren, refs)
|
|
}
|
|
}
|
|
|
|
func (v *viewObject) searchObjectRowID(parentObjectRowID uuid.UUID) *viewObject {
|
|
if v.ObjectRowID == parentObjectRowID {
|
|
return v
|
|
}
|
|
for _, child := range v.Children {
|
|
if f := child.searchObjectRowID(parentObjectRowID); f != nil {
|
|
return f
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *viewObject) addChild(objectRowID uuid.UUID, payload storage.Payload) {
|
|
child := createViewObject(objectRowID, payload, v)
|
|
v.Children = append(v.Children, child)
|
|
}
|
|
|
|
func (v *viewObject) applyView(mapper viewObjectMapper) {
|
|
v.ViewContext = mapper(v.ObjectRowID, v.Raw, v.ViewContext)
|
|
for _, child := range v.Children {
|
|
child.applyView(mapper)
|
|
}
|
|
}
|
|
|
|
func (v *viewObject) sort(by func(v1, v2 *viewObject) bool) {
|
|
if len(v.Children) > 0 {
|
|
vos := &viewObjectSorter{
|
|
viewObjects: v.Children,
|
|
by: by,
|
|
}
|
|
sort.Sort(vos)
|
|
for _, child := range v.Children {
|
|
child.sort(by)
|
|
}
|
|
}
|
|
}
|
|
|
|
func createViewObject(objectRowID uuid.UUID, payload storage.Payload, parent *viewObject) *viewObject {
|
|
return &viewObject{
|
|
ObjectRowID: objectRowID,
|
|
Raw: payload,
|
|
ViewContext: &viewObjectContext{},
|
|
Parent: parent,
|
|
Children: make([]*viewObject, 0),
|
|
}
|
|
}
|