Implemented conversation threading, fixed #6

pull/24/head
マリウス 2 years ago
parent 7d5da5d80c
commit 19adc94508
No known key found for this signature in database
GPG Key ID: 272ED814BF63261F

@ -214,8 +214,11 @@ func (db *Database) GetArticleByID(id string) (models.Article, error) {
return article, nil
}
func (db *Database) ListArticles() ([]models.Article, error) {
var articles []models.Article
func (db *Database) ListArticles() ([]*models.Article, []*models.Article, error) {
var articles []*models.Article
var articlesMap map[string]*models.Article
articlesMap = make(map[string]*models.Article)
_, err := db.Store.Query(db.ctx, func(e interface{})(bool, error) {
entity := e.(map[string]interface{})
@ -223,20 +226,36 @@ func (db *Database) ListArticles() ([]models.Article, error) {
var article models.Article
err := mapstructure.Decode(entity, &article)
if err == nil {
articles = append(articles, article)
// TODO: Not sure why mapstructure won't convert this field and simply
// leave it ""
if entity["in-reply-to-id"] != nil {
article.InReplyToID = entity["in-reply-to-id"].(string)
}
articles = append(articles, &article)
articlesMap[article.ID] = articles[(len(articles) - 1)]
}
return true, err
}
return false, nil
})
if err != nil {
return articles, err
return articles, nil, err
}
sort.SliceStable(articles, func(i, j int) bool {
return articles[i].Date > articles[j].Date
})
return articles, nil
var articlesRoots []*models.Article
for i := 0; i < len(articles); i++ {
if articles[i].InReplyToID != "" {
(*articlesMap[articles[i].InReplyToID]).Replies =
append((*articlesMap[articles[i].InReplyToID]).Replies, articles[i])
} else {
articlesRoots = append(articlesRoots, articles[i])
}
}
return articles, articlesRoots, nil
}

@ -16,6 +16,8 @@ type Article struct {
Date int64 `mmapstructure:"date" json:"date" validate:"required,number"`
Organization string `mmapstructure:"organization" json:"organization" validate:"printascii"`
Body string `mmapstructure:"body" json:"body" validate:"required,min=3,max=524288"`
Replies []*Article `mmapstructure:"-" json:"-" validate:"-"`
}
func NewArticle() (*Article) {

@ -42,10 +42,12 @@ func main() {
log.Panicln(err)
}
var articles []models.Article
var articles []*models.Article
var articlesRoots []*models.Article
TUI := tui.Init(&EMBEDFS, cfg, logger)
TUI.ArticlesDatasource = &articles
TUI.ArticlesRoots = &articlesRoots
db, err := database.NewDatabase(ctx, cfg.ConnectionString, cfg.CachePath, logger)
if err != nil {
@ -54,7 +56,7 @@ func main() {
defer db.Disconnect()
TUI.CallbackRefreshArticles = func() (error) {
articles, err = db.ListArticles()
articles, articlesRoots, err = db.ListArticles()
return err
}
TUI.CallbackSubmitArticle = func(article *models.Article) (error) {
@ -63,7 +65,7 @@ func main() {
err = db.Connect(func(address string) {
TUI.Views["mainscreen"].(*tui.Mainscreen).SetFooter(address)
articles, _ = db.ListArticles()
articles, articlesRoots, _ = db.ListArticles()
time.Sleep(time.Second * 2)
TUI.SetView("mainscreen", true)

@ -169,41 +169,52 @@ func (mainscreen *Mainscreen) GetDefaultFocus() (tview.Primitive) {
return mainscreen.Articles
}
func(mainscreen *Mainscreen) Refresh() {
selectedGroup := mainscreen.CurrentGroupSelected
selectedArticle := mainscreen.CurrentArticleSelected
func(mainscreen *Mainscreen) addNodeToArticlesList(level int, articlesNode *[]*models.Article, selectedGroup int, previousGroupsList []string) {
// fmt.Fprintf(os.Stderr, "%s Node has %d items\n", strings.Repeat(" ", level * 3), len(*articlesNode))
previousGroupsList := mainscreen.GroupsList
mainscreen.GroupsList = []string{}
// previousGroupsMap := mainscreen.GroupsMap
mainscreen.GroupsMap = make(map[string]GroupMapEntry)
mainscreen.Groups.Clear()
for i := 0; i < len(*articlesNode); i++ {
article := (*articlesNode)[i]
mainscreen.ArticlesList = []*models.Article{}
mainscreen.Articles.Clear()
// fmt.Fprintf(os.Stderr, "%s Item has ID %s and is in reply of ID %s and has %d replies\n", strings.Repeat(" ", level * 3), article.ID, article.InReplyToID, len(article.Replies))
mainscreen.GroupsList = append(mainscreen.GroupsList, "*")
mainscreen.GroupsMap["*"] = GroupMapEntry{
Index: 0,
}
for i := 0; i < len(*mainscreen.T.ArticlesDatasource); i++ {
article := (*mainscreen.T.ArticlesDatasource)[i]
if selectedGroup == 0 ||
(selectedGroup != 0 &&
article.Newsgroup == previousGroupsList[selectedGroup]) {
prefix := ""
if level > 0 {
if i < (len(*articlesNode) - 1) || len(article.Replies) > 0 {
prefix = "[gray]├[-]"
} else {
prefix = "[gray]└[-]"
}
}
prefixSub := " "
if len(article.Replies) > 0 || (level > 0 && i < (len(*articlesNode) - 1)) {
prefixSub = "[gray]│[-]"
}
mainscreen.Articles.AddItem(
fmt.Sprintf(
"%s",
"%s%s%s",
prefix,
strings.Repeat(" ", level),
article.Subject,
),
fmt.Sprintf(
" on [darkgray]%s[-] by [darkgray]%s[-] in [darkgray]%s[-]",
"%s%s on [darkgray]%s[-] by [darkgray]%s[-] in [darkgray]%s[-]",
prefixSub,
strings.Repeat(" ", level),
MillisecondsToDate(article.Date),
article.From,
article.Newsgroup,
), 0, nil)
mainscreen.ArticlesList = append(mainscreen.ArticlesList, &article)
mainscreen.ArticlesList = append(mainscreen.ArticlesList, article)
if len(article.Replies) > 0 {
mainscreen.addNodeToArticlesList((level + 1), &article.Replies, selectedGroup, previousGroupsList)
}
}
if _, ok := mainscreen.GroupsMap[article.Newsgroup]; !ok {
@ -213,6 +224,27 @@ func(mainscreen *Mainscreen) Refresh() {
}
}
}
}
func(mainscreen *Mainscreen) Refresh() {
selectedGroup := mainscreen.CurrentGroupSelected
selectedArticle := mainscreen.CurrentArticleSelected
previousGroupsList := mainscreen.GroupsList
mainscreen.GroupsList = []string{}
// previousGroupsMap := mainscreen.GroupsMap
mainscreen.GroupsMap = make(map[string]GroupMapEntry)
mainscreen.Groups.Clear()
mainscreen.ArticlesList = []*models.Article{}
mainscreen.Articles.Clear()
mainscreen.GroupsList = append(mainscreen.GroupsList, "*")
mainscreen.GroupsMap["*"] = GroupMapEntry{
Index: 0,
}
mainscreen.addNodeToArticlesList(0, mainscreen.T.ArticlesRoots, selectedGroup, previousGroupsList)
sort.Strings(mainscreen.GroupsList)
for idx, group := range mainscreen.GroupsList {

@ -22,7 +22,8 @@ type TUI struct {
ModalVisible bool
ModalButtons map[string]ModalButton
ArticlesDatasource *[]models.Article
ArticlesDatasource *[]*models.Article
ArticlesRoots *[]*models.Article
CallbackRefreshArticles func() (error)
CallbackSubmitArticle func(article *models.Article) (error)

Loading…
Cancel
Save