diff --git a/internal/database/chapter.go b/internal/database/chapter.go new file mode 100644 index 0000000..e4f8127 --- /dev/null +++ b/internal/database/chapter.go @@ -0,0 +1,62 @@ +package database + +import ( + "database/sql" + "sync" +) + +type Chapter struct { + Id int + Manga *Manga + Url string + Name string + Number int + TimeStampUnix int64 +} + +type ChapterTable[K comparable] struct { + mutex sync.Mutex + chapters map[K]Chapter + updated map[K]DbStatus +} + +func (c *ChapterTable[K]) Get(key K) (Chapter, bool) { + c.mutex.Lock() + defer c.mutex.Unlock() + val, ok := c.chapters[key] + return val, ok +} + +func (c *ChapterTable[K]) Set(key K, new Chapter) { + c.mutex.Lock() + defer c.mutex.Unlock() + val, ok := c.updated[key] + if ok && val == Loaded { + c.updated[key] = Updated + } else { + c.updated[key] = New + } + c.chapters[key] = new +} + +func (c *ChapterTable[K]) All() []Chapter { + c.mutex.Lock() + defer c.mutex.Unlock() + res := make([]Chapter, len(c.chapters)) + counter := 0 + for _, chapter := range c.chapters { + res[counter] = chapter + counter++ + } + return res +} + +func (c *ChapterTable[K]) Save(db *sql.DB) error { + //TODO implement me + panic("implement me") +} + +func (c *ChapterTable[K]) Load(db *sql.DB) error { + //TODO implement me + panic("implement me") +} diff --git a/internal/database/database.go b/internal/database/database.go index 23e6dae..57cd82d 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -10,26 +10,6 @@ import ( _ "github.com/mattn/go-sqlite3" ) -type Manga struct { - Id int - Title string - TimeStampUnix int64 - Thumbnail *bytes.Buffer - LastChapterNum int - - // Not in DB - LatestChapter *Chapter -} - -type Chapter struct { - Id int - Manga *Manga - Url string - Name string - Number int - TimeStampUnix int64 -} - type Manager struct { ConnectionString string db *sql.DB diff --git a/internal/database/manga.go b/internal/database/manga.go new file mode 100644 index 0000000..19ca9b9 --- /dev/null +++ b/internal/database/manga.go @@ -0,0 +1,94 @@ +package database + +import ( + "bytes" + "database/sql" + "sync" +) + +type Manga struct { + Id int + Title string + TimeStampUnix int64 + Thumbnail *bytes.Buffer + LastChapterNum int + + // Not in DB + LatestChapter *Chapter +} + +type MangaTable[K comparable] struct { + mutex sync.Mutex + mangas map[K]Manga + updated map[K]DbStatus +} + +func (m *MangaTable[K]) Get(key K) (Manga, bool) { + m.mutex.Lock() + defer m.mutex.Unlock() + val, ok := m.mangas[key] + return val, ok +} + +func (m *MangaTable[K]) Set(key K, new Manga) { + m.mutex.Lock() + defer m.mutex.Unlock() + val, ok := m.updated[key] + if ok && val == Loaded { + m.updated[key] = Updated + } else { + m.updated[key] = New + } + m.mangas[key] = new +} + +func (m *MangaTable[K]) All() []Manga { + m.mutex.Lock() + defer m.mutex.Unlock() + res := make([]Manga, len(m.mangas)) + counter := 0 + for _, manga := range m.mangas { + res[counter] = manga + counter++ + } + return res +} + +func (m *MangaTable[K]) Save(db *sql.DB) error { + m.mutex.Lock() + defer m.mutex.Unlock() + for k, status := range m.updated { + if status == Loaded { + continue + } else if status == Updated { + manga := m.mangas[k] + err := updateManga(db, &manga) + if err != nil { + return err + } + } else { + manga := m.mangas[k] + err := insertManga(db, &manga) + if err != nil { + return err + } + } + } + return nil +} + +func (m *MangaTable[K]) Load(db *sql.DB) error { + panic("") +} + +func updateManga(db *sql.DB, m *Manga) error { + const cmd = "UPDATE Manga set Title = ?, TimeStampUnixEpoch = ?, Thumbnail = ?, LatestAvailableChapter = ? WHERE ID = ?" + _, err := db.Exec(cmd, m.Title, m.TimeStampUnix, m.Thumbnail.Bytes(), m.LastChapterNum, m.Id) + return err +} + +func insertManga(db *sql.DB, manga *Manga) error { + const cmd = "INSERT INTO Manga(ID, Title, TimeStampUnixEpoch, Thumbnail, LatestAvailableChapter) values(?, ?, ?, ?, ?)" + _, err := db.Exec(cmd, manga.Id, manga.Title, manga.TimeStampUnix, manga.Thumbnail.Bytes(), manga.LastChapterNum) + return err +} diff --git a/internal/database/table.go b/internal/database/table.go new file mode 100644 index 0000000..1cc787c --- /dev/null +++ b/internal/database/table.go @@ -0,0 +1,20 @@ +package database + +import "database/sql" + +type DbStatus int + +const ( + New DbStatus = iota + Loaded + Updated +) + +// Table TODO: This Could probably be a generic instead of interface / both +type Table[K comparable, T any] interface { + Get(key K) (T, bool) + Set(key K, new T) + All() []T + Save(db *sql.DB) error + Load(db *sql.DB) error +} diff --git a/internal/server/server.go b/internal/server/server.go index ee76c68..50ee4a0 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -61,6 +61,17 @@ func (s *Server) Start() error { // Update Latest Chapter every 5 Minutes go func(s *Server) { + time.AfterFunc(time.Second*10, func() { + s.DbMgr.Rw.Lock() + for _, m := range s.DbMgr.Mangas { + err := s.UpdateLatestAvailableChapter(m) + if err != nil { + fmt.Println(err) + } + } + s.DbMgr.Rw.Unlock() + }) + for { select { case <-time.After(time.Minute * 5): diff --git a/internal/view/Views/menu.gohtml b/internal/view/Views/menu.gohtml index dc4a5c0..07b090b 100644 --- a/internal/view/Views/menu.gohtml +++ b/internal/view/Views/menu.gohtml @@ -141,7 +141,7 @@ {{.Number}} / {{.LastNumber}} {{.LastTime}} - + diff --git a/internal/view/Views/viewer.gohtml b/internal/view/Views/viewer.gohtml index 98f98e6..c06b7c3 100644 --- a/internal/view/Views/viewer.gohtml +++ b/internal/view/Views/viewer.gohtml @@ -31,6 +31,12 @@ vertical-align: middle; } + @media (max-width: 500px) { + .scroll-container img { + width: 100%; + } + } + /* * I have no clue what css is, jesus christ ... */ @@ -45,6 +51,18 @@ display: flex; } + .fixed-button { + position: fixed; + bottom: 80px; + right: 15px; + margin-bottom: 40px; + z-index: 999; + } + + .text{ + color: white; + } + .button-36 { background-image: linear-gradient(92.88deg, #455EB5 9.16%, #5643CC 43.89%, #673FD7 64.72%); border-radius: 8px; @@ -79,13 +97,17 @@ -
+

{{.Title}}

+
+
{{range .Images}} img_{{.Index}}