Implemented cache and read/unread feature #22

pull/34/head
マリウス 2 years ago
parent ee4b9c8125
commit a3c94bad2c
No known key found for this signature in database
GPG Key ID: 272ED814BF63261F

55
cache/cache.go vendored

@ -0,0 +1,55 @@
package cache
import (
"encoding/json"
"github.com/mrusme/superhighway84/models"
"github.com/tidwall/buntdb"
)
type Cache struct {
db *buntdb.DB
}
func NewCache() (*Cache, error) {
var err error
cache := new(Cache)
cache.db, err = buntdb.Open(":memory:")
if err != nil {
return nil, err
}
return cache, nil
}
func(cache *Cache) Close() {
cache.db.Close()
}
func(cache *Cache) StoreArticle(article *models.Article) (error) {
modelJson, jsonErr := json.Marshal(article)
if jsonErr != nil {
return jsonErr
}
err := cache.db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(article.ID, string(modelJson), nil)
return err
})
return err
}
func(cache *Cache) LoadArticle(article *models.Article) (error) {
err := cache.db.View(func(tx *buntdb.Tx) error {
value, err := tx.Get(article.ID)
if err != nil{
return err
}
json.Unmarshal([]byte(value), article)
return nil
})
return err
}

@ -18,6 +18,7 @@ import (
"github.com/mitchellh/mapstructure"
"go.uber.org/zap"
"github.com/mrusme/superhighway84/cache"
"github.com/mrusme/superhighway84/models"
)
@ -25,7 +26,8 @@ type Database struct {
ctx context.Context
ConnectionString string
URI string
Cache string
CachePath string
Cache *cache.Cache
Logger *zap.Logger
@ -41,7 +43,7 @@ func (db *Database) init() (error) {
var err error
db.OrbitDB, err = orbitdb.NewOrbitDB(db.ctx, db.IPFSCoreAPI, &orbitdb.NewOrbitDBOptions{
Directory: &db.Cache,
Directory: &db.CachePath,
Logger: db.Logger,
})
if err != nil {
@ -108,6 +110,7 @@ func NewDatabase(
ctx context.Context,
dbConnectionString string,
dbCache string,
cch *cache.Cache,
logger *zap.Logger,
) (*Database, error) {
var err error
@ -115,7 +118,8 @@ func NewDatabase(
db := new(Database)
db.ctx = ctx
db.ConnectionString = dbConnectionString
db.Cache = dbCache
db.CachePath = dbCache
db.Cache = cch
db.Logger = logger
defaultPath, err := config.PathRoot()
@ -231,6 +235,7 @@ func (db *Database) ListArticles() ([]*models.Article, []*models.Article, error)
if entity["in-reply-to-id"] != nil {
article.InReplyToID = entity["in-reply-to-id"].(string)
}
db.Cache.LoadArticle(&article)
articles = append(articles, &article)
articlesMap[article.ID] = articles[(len(articles) - 1)]
}

@ -196,6 +196,14 @@ require (
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/tidwall/btree v1.1.0 // indirect
github.com/tidwall/buntdb v1.2.9 // indirect
github.com/tidwall/gjson v1.12.1 // indirect
github.com/tidwall/grect v0.1.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/rtred v0.1.2 // indirect
github.com/tidwall/tinyqueue v0.1.1 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect

@ -1216,6 +1216,24 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8=
github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
github.com/tidwall/buntdb v1.2.9 h1:XVz684P7X6HCTrdr385yDZWB1zt/n20ZNG3M1iGyFm4=
github.com/tidwall/buntdb v1.2.9/go.mod h1:IwyGSvvDg6hnKSIhtdZ0AqhCZGH8ukdtCAzaP8fI1X4=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
github.com/tidwall/grect v0.1.4/go.mod h1:9FBsaYRaR0Tcy4UwefBX/UDcDcDy9V5jUcxHzv2jd5Q=
github.com/tidwall/lotsa v1.0.2/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8=
github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ=
github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE=
github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=

@ -8,16 +8,17 @@ import (
)
type Article struct {
ID string `mmapstructure:"id" json:"id" validate:"uuid_rfc4122"`
InReplyToID string `mmapstructure:"in-reply-to-id" json:"in-reply-to-id" validate:"omitempty,uuid_rfc4122"`
From string `mmapstructure:"from" json:"from" validate:"required,printascii"`
Newsgroup string `mmapstructure:"newsgroup" json:"newsgroup" validate:"required,min=2,max=80,printascii,lowercase"`
Subject string `mmapstructure:"subject" json:"subject" validate:"required,min=2,max=128,printascii"`
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"`
ID string `mmapstructure:"id" json:"-" validate:"uuid_rfc4122"`
InReplyToID string `mmapstructure:"in-reply-to-id" json:"-" validate:"omitempty,uuid_rfc4122"`
From string `mmapstructure:"from" json:"-" validate:"required,printascii"`
Newsgroup string `mmapstructure:"newsgroup" json:"-" validate:"required,min=2,max=80,printascii,lowercase"`
Subject string `mmapstructure:"subject" json:"-" validate:"required,min=2,max=128,printascii"`
Date int64 `mmapstructure:"date" json:"-" validate:"required,number"`
Organization string `mmapstructure:"organization" json:"-" validate:"printascii"`
Body string `mmapstructure:"body" json:"-" validate:"required,min=3,max=524288"`
Replies []*Article `mmapstructure:"-" json:"-" validate:"-"`
Read bool `mmapstructure:"-" json:"read" validate:"-"`
}
func NewArticle() (*Article) {

@ -12,6 +12,7 @@ import (
"log"
"github.com/mrusme/superhighway84/cache"
"github.com/mrusme/superhighway84/config"
"github.com/mrusme/superhighway84/database"
"github.com/mrusme/superhighway84/models"
@ -61,16 +62,23 @@ func main() {
log.Panicln(err)
}
cch, err := cache.NewCache()
if err != nil {
log.Panicln(err)
}
defer cch.Close()
var articles []*models.Article
var articlesRoots []*models.Article
TUI := tui.Init(&EMBEDFS, cfg, logger)
TUI := tui.Init(&EMBEDFS, cfg, cch, logger)
TUI.SetVersion(version, getLatestVersion())
TUI.ArticlesDatasource = &articles
TUI.ArticlesRoots = &articlesRoots
db, err := database.NewDatabase(ctx, cfg.ConnectionString, cfg.CachePath, logger)
db, err := database.NewDatabase(ctx, cfg.ConnectionString, cfg.CachePath, cch, logger)
if err != nil {
log.Panicln(err)
}

@ -28,6 +28,10 @@ var STATS_TEMPLATE =
`
var INFO_TEMPLATE = "%s"
const (
COLOR_SUBJECT_UNREAD = "teal"
COLOR_SUBJECT_READ = "white"
)
type GroupMapEntry struct {
Index int
@ -225,11 +229,17 @@ func(mainscreen *Mainscreen) addNodeToArticlesList(level int, articlesNode *[]*m
prefixSub = "[gray]│[-]"
}
subjectColor := COLOR_SUBJECT_UNREAD
if article.Read == true {
subjectColor = COLOR_SUBJECT_READ
}
mainscreen.Articles.AddItem(
fmt.Sprintf(
"%s%s%s",
"%s%s[%s]%s[-]",
prefix,
strings.Repeat(" ", level),
subjectColor,
article.Subject,
),
fmt.Sprintf(
@ -347,6 +357,7 @@ func(mainscreen *Mainscreen) changeHandler(item string)(func(int, string, string
}
mainscreen.CurrentArticleSelected = index
mainscreen.renderPreview(mainscreen.ArticlesList[index])
mainscreen.markAsRead(index, mainscreen.ArticlesList[index])
}
}
}
@ -372,6 +383,19 @@ func(mainscreen *Mainscreen) renderPreview(article *models.Article) {
mainscreen.Preview.ScrollToBeginning()
}
func(mainscreen *Mainscreen) markAsRead(index int, article *models.Article) {
article.Read = true
mainText, secondaryText := mainscreen.Articles.GetItemText(index)
updatedMainText := strings.Replace(
mainText,
fmt.Sprintf("[%s]", COLOR_SUBJECT_UNREAD),
fmt.Sprintf("[%s]", COLOR_SUBJECT_READ),
1,
)
mainscreen.Articles.SetItemText(index, updatedMainText, secondaryText)
mainscreen.T.Cache.StoreArticle(article)
}
func(mainscreen *Mainscreen) submitNewArticle(group string) {
newArticle := models.NewArticle()

@ -7,6 +7,7 @@ import (
"unicode"
"github.com/gdamore/tcell/v2"
"github.com/mrusme/superhighway84/cache"
"github.com/mrusme/superhighway84/config"
"github.com/mrusme/superhighway84/models"
"github.com/rivo/tview"
@ -29,6 +30,7 @@ type TUI struct {
CallbackSubmitArticle func(article *models.Article) (error)
Config *config.Config
Cache *cache.Cache
Logger *zap.Logger
Stats map[string]int64
@ -51,7 +53,7 @@ type ModalButton struct {
Callback func()
}
func Init(embedfs *embed.FS, cfg *config.Config, logger *zap.Logger) (*TUI) {
func Init(embedfs *embed.FS, cfg *config.Config, cch *cache.Cache, logger *zap.Logger) (*TUI) {
t := new(TUI)
tview.Styles = tview.Theme{
@ -70,6 +72,7 @@ func Init(embedfs *embed.FS, cfg *config.Config, logger *zap.Logger) (*TUI) {
t.App = tview.NewApplication()
t.Config = cfg
t.Cache = cch
t.Logger = logger
t.Stats = make(map[string]int64)

Loading…
Cancel
Save