Added Thumbnails and saving those to db,
also added Log for Locking and unlocking Rw, because there was a Problem with that, and now it stays
This commit is contained in:
@@ -46,6 +46,7 @@ func main() {
|
|||||||
http.HandleFunc("POST /next", s.HandleNext)
|
http.HandleFunc("POST /next", s.HandleNext)
|
||||||
http.HandleFunc("POST /prev", s.HandlePrev)
|
http.HandleFunc("POST /prev", s.HandlePrev)
|
||||||
http.HandleFunc("POST /exit", s.HandleExit)
|
http.HandleFunc("POST /exit", s.HandleExit)
|
||||||
|
http.HandleFunc("POST /delete", s.HandleDelete)
|
||||||
|
|
||||||
fmt.Println("Server starting...")
|
fmt.Println("Server starting...")
|
||||||
err = http.ListenAndServe(":8000", nil)
|
err = http.ListenAndServe(":8000", nil)
|
||||||
@@ -55,7 +56,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(db *database.DatabaseManager) {
|
func Close(db *database.Manager) {
|
||||||
fmt.Println("Attempting to save and close DB")
|
fmt.Println("Attempting to save and close DB")
|
||||||
err := db.Save()
|
err := db.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
create table if not exists Manga (
|
create table if not exists Manga (
|
||||||
ID integer not null primary key,
|
ID integer not null primary key,
|
||||||
Title text,
|
Title text,
|
||||||
TimeStampUnixEpoch int
|
TimeStampUnixEpoch int,
|
||||||
|
Thumbnail blob
|
||||||
);
|
);
|
||||||
|
|
||||||
create table if not exists Chapter (
|
create table if not exists Chapter (
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
@@ -12,6 +14,7 @@ type Manga struct {
|
|||||||
Id int
|
Id int
|
||||||
Title string
|
Title string
|
||||||
TimeStampUnix int64
|
TimeStampUnix int64
|
||||||
|
Thumbnail *bytes.Buffer
|
||||||
|
|
||||||
// Not in DB
|
// Not in DB
|
||||||
LatestChapter *Chapter
|
LatestChapter *Chapter
|
||||||
@@ -26,7 +29,7 @@ type Chapter struct {
|
|||||||
TimeStampUnix int64
|
TimeStampUnix int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseManager struct {
|
type Manager struct {
|
||||||
ConnectionString string
|
ConnectionString string
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
|
|
||||||
@@ -37,8 +40,8 @@ type DatabaseManager struct {
|
|||||||
CreateIfNotExists bool
|
CreateIfNotExists bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabase(connectionString string, createIfNotExists bool) DatabaseManager {
|
func NewDatabase(connectionString string, createIfNotExists bool) Manager {
|
||||||
return DatabaseManager{
|
return Manager{
|
||||||
ConnectionString: connectionString,
|
ConnectionString: connectionString,
|
||||||
Rw: &sync.Mutex{},
|
Rw: &sync.Mutex{},
|
||||||
Mangas: make(map[int]*Manga),
|
Mangas: make(map[int]*Manga),
|
||||||
@@ -47,7 +50,7 @@ func NewDatabase(connectionString string, createIfNotExists bool) DatabaseManage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbMgr *DatabaseManager) Open() error {
|
func (dbMgr *Manager) Open() error {
|
||||||
db, err := sql.Open("sqlite3", dbMgr.ConnectionString)
|
db, err := sql.Open("sqlite3", dbMgr.ConnectionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -63,7 +66,7 @@ func (dbMgr *DatabaseManager) Open() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbMgr *DatabaseManager) Close() error {
|
func (dbMgr *Manager) Close() error {
|
||||||
err := dbMgr.db.Close()
|
err := dbMgr.db.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -75,11 +78,43 @@ func (dbMgr *DatabaseManager) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbMgr *DatabaseManager) Save() error {
|
func (dbMgr *Manager) Delete(mangaId int) error {
|
||||||
|
db := dbMgr.db
|
||||||
|
fmt.Println("Locking Rw in database.go:84")
|
||||||
|
dbMgr.Rw.Lock()
|
||||||
|
defer func() {
|
||||||
|
fmt.Println("Unlocking Rw in database.go:87")
|
||||||
|
dbMgr.Rw.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err := db.Exec("DELETE from Chapter where MangaID = ?", mangaId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Exec("DELETE from Manga where ID = ?", mangaId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, chapter := range dbMgr.Chapters {
|
||||||
|
if chapter.Manga.Id == mangaId {
|
||||||
|
delete(dbMgr.Chapters, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(dbMgr.Mangas, mangaId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbMgr *Manager) Save() error {
|
||||||
db := dbMgr.db
|
db := dbMgr.db
|
||||||
|
|
||||||
|
fmt.Println("Locking Rw in database.go:113")
|
||||||
dbMgr.Rw.Lock()
|
dbMgr.Rw.Lock()
|
||||||
defer dbMgr.Rw.Unlock()
|
defer func() {
|
||||||
|
fmt.Println("Unlocking Rw in database.go:116")
|
||||||
|
dbMgr.Rw.Unlock()
|
||||||
|
}()
|
||||||
for _, m := range dbMgr.Mangas {
|
for _, m := range dbMgr.Mangas {
|
||||||
count := 0
|
count := 0
|
||||||
err := db.QueryRow("SELECT COUNT(*) FROM Manga where ID = ?", m.Id).Scan(&count)
|
err := db.QueryRow("SELECT COUNT(*) FROM Manga where ID = ?", m.Id).Scan(&count)
|
||||||
@@ -88,10 +123,17 @@ func (dbMgr *DatabaseManager) Save() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
_, err := db.Exec("INSERT INTO Manga(ID, Title, TimeStampUnixEpoch) values(?, ?, ?)", m.Id, m.Title, m.TimeStampUnix)
|
if m.Thumbnail != nil {
|
||||||
|
_, err := db.Exec("INSERT INTO Manga(ID, Title, TimeStampUnixEpoch, Thumbnail) values(?, ?, ?, ?)", m.Id, m.Title, m.TimeStampUnix, m.Thumbnail.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_, err := db.Exec("INSERT INTO Manga(ID, Title, TimeStampUnixEpoch ) values(?, ?, ?)", m.Id, m.Title, m.TimeStampUnix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err := db.Exec("UPDATE Manga set Title = ?, TimeStampUnixEpoch = ? WHERE ID = ?", m.Title, m.TimeStampUnix, m.Id)
|
_, err := db.Exec("UPDATE Manga set Title = ?, TimeStampUnixEpoch = ? WHERE ID = ?", m.Title, m.TimeStampUnix, m.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -126,16 +168,20 @@ func (dbMgr *DatabaseManager) Save() error {
|
|||||||
//go:embed createDb.sql
|
//go:embed createDb.sql
|
||||||
var createSql string
|
var createSql string
|
||||||
|
|
||||||
func (dbMgr *DatabaseManager) createDatabaseIfNotExists() error {
|
func (dbMgr *Manager) createDatabaseIfNotExists() error {
|
||||||
_, err := dbMgr.db.Exec(createSql)
|
_, err := dbMgr.db.Exec(createSql)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbMgr *DatabaseManager) load() error {
|
func (dbMgr *Manager) load() error {
|
||||||
db := dbMgr.db
|
db := dbMgr.db
|
||||||
|
|
||||||
|
fmt.Println("Locking Rw in database.go:180")
|
||||||
dbMgr.Rw.Lock()
|
dbMgr.Rw.Lock()
|
||||||
defer dbMgr.Rw.Unlock()
|
defer func() {
|
||||||
|
fmt.Println("Unlocking Rw in database.go:183")
|
||||||
|
dbMgr.Rw.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
rows, err := db.Query("SELECT * FROM Manga")
|
rows, err := db.Query("SELECT * FROM Manga")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -144,7 +190,7 @@ func (dbMgr *DatabaseManager) load() error {
|
|||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
manga := Manga{}
|
manga := Manga{}
|
||||||
if err = rows.Scan(&manga.Id, &manga.Title, &manga.TimeStampUnix); err != nil {
|
if err = rows.Scan(&manga.Id, &manga.Title, &manga.TimeStampUnix, &manga.Thumbnail); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dbMgr.Mangas[manga.Id] = &manga
|
dbMgr.Mangas[manga.Id] = &manga
|
||||||
|
|||||||
@@ -108,3 +108,40 @@ func (b *Bato) GetTitleIdAndChapterId(url string) (titleId int, chapterId int, e
|
|||||||
|
|
||||||
return t, c, err
|
return t, c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//func (b *Bato) GetChapterList(url string) (chapterIds []int, err error) {
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (b *Bato) GetThumbnail(subUrl string) (thumbnailUrl string, err error) {
|
||||||
|
url := fmt.Sprintf("https://bato.to/title/%s", subUrl)
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
|
||||||
|
// TODO: Testing for above 300 is dirty
|
||||||
|
if err != nil && resp.StatusCode > 300 {
|
||||||
|
return "", errors.New("could not get html")
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Could not close body because: %v\n", err)
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
all, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
h := string(all)
|
||||||
|
|
||||||
|
reg, err := regexp.Compile(`<img data-hk="0-1-0" .*? src="(.*?)["']`)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
match := reg.FindStringSubmatch(h)
|
||||||
|
if len(match) <= 1 {
|
||||||
|
return "", errors.New("could not find Thumbnail url")
|
||||||
|
}
|
||||||
|
|
||||||
|
return match[1], nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ type Provider interface {
|
|||||||
GetPrev(html string) (url string, err error)
|
GetPrev(html string) (url string, err error)
|
||||||
GetTitleAndChapter(url string) (title string, chapter string, err error)
|
GetTitleAndChapter(url string) (title string, chapter string, err error)
|
||||||
GetTitleIdAndChapterId(url string) (titleId int, chapterId int, err error)
|
GetTitleIdAndChapterId(url string) (titleId int, chapterId int, err error)
|
||||||
|
GetThumbnail(mangaId string) (thumbnailUrl string, err error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,12 @@ func (s *Server) HandleNew(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
||||||
tmpl := template.Must(view.GetViewTemplate(view.Menu))
|
tmpl := template.Must(view.GetViewTemplate(view.Menu))
|
||||||
|
|
||||||
|
fmt.Println("Locking Rw in handler.go:43")
|
||||||
s.DbMgr.Rw.Lock()
|
s.DbMgr.Rw.Lock()
|
||||||
defer s.DbMgr.Rw.Unlock()
|
defer func() {
|
||||||
|
fmt.Println("Unlocking Rw in handler.go:46")
|
||||||
|
s.DbMgr.Rw.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
all := s.DbMgr.Mangas
|
all := s.DbMgr.Mangas
|
||||||
l := len(all)
|
l := len(all)
|
||||||
@@ -50,12 +54,20 @@ func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
|||||||
for _, manga := range all {
|
for _, manga := range all {
|
||||||
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
||||||
|
|
||||||
|
thumbnail, err := s.LoadThumbnail(manga.Id)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
manga.Thumbnail = s.ImageBuffers[thumbnail]
|
||||||
|
|
||||||
mangaViewModels[counter] = view.MangaViewModel{
|
mangaViewModels[counter] = view.MangaViewModel{
|
||||||
|
ID: manga.Id,
|
||||||
Title: title,
|
Title: title,
|
||||||
Number: manga.LatestChapter.Number,
|
Number: manga.LatestChapter.Number,
|
||||||
// I Hate this time Format... 15 = hh, 04 = mm, 02 = DD, 01 = MM, 06 == YY
|
// I Hate this time Format... 15 = hh, 04 = mm, 02 = DD, 01 = MM, 06 == YY
|
||||||
LastTime: time.Unix(manga.TimeStampUnix, 0).Format("15:04 (02-01-06)"),
|
LastTime: time.Unix(manga.TimeStampUnix, 0).Format("15:04 (02-01-06)"),
|
||||||
Url: manga.LatestChapter.Url,
|
Url: manga.LatestChapter.Url,
|
||||||
|
ThumbnailUrl: thumbnail,
|
||||||
}
|
}
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
@@ -74,6 +86,29 @@ func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
mangaStr := r.PostFormValue("mangaId")
|
||||||
|
|
||||||
|
if mangaStr == "" {
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mangaId, err := strconv.Atoi(mangaStr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.DbMgr.Delete(mangaId)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
||||||
err := s.DbMgr.Save()
|
err := s.DbMgr.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,8 +122,12 @@ func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
||||||
tmpl := template.Must(view.GetViewTemplate(view.Viewer))
|
tmpl := template.Must(view.GetViewTemplate(view.Viewer))
|
||||||
|
|
||||||
|
fmt.Println("Locking Rw in handler.go:125")
|
||||||
s.DbMgr.Rw.Lock()
|
s.DbMgr.Rw.Lock()
|
||||||
defer s.DbMgr.Rw.Unlock()
|
defer func() {
|
||||||
|
fmt.Println("Unlocking Rw in handler.go:128")
|
||||||
|
s.DbMgr.Rw.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
mangaId, chapterId, err := s.Provider.GetTitleIdAndChapterId(s.CurrSubUrl)
|
mangaId, chapterId, err := s.Provider.GetTitleIdAndChapterId(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -144,6 +183,7 @@ func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
|||||||
func (s *Server) HandleImage(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandleImage(w http.ResponseWriter, r *http.Request) {
|
||||||
u := r.PathValue("url")
|
u := r.PathValue("url")
|
||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
|
defer s.Mutex.Unlock()
|
||||||
buf := s.ImageBuffers[u]
|
buf := s.ImageBuffers[u]
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
fmt.Printf("url: %s is nil\n", u)
|
fmt.Printf("url: %s is nil\n", u)
|
||||||
@@ -156,7 +196,6 @@ func (s *Server) HandleImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
s.Mutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"mangaGetter/internal/view"
|
"mangaGetter/internal/view"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,7 @@ type Server struct {
|
|||||||
IsFirst bool
|
IsFirst bool
|
||||||
IsLast bool
|
IsLast bool
|
||||||
|
|
||||||
DbMgr *database.DatabaseManager
|
DbMgr *database.Manager
|
||||||
|
|
||||||
// I'm not even sure if this helps.
|
// I'm not even sure if this helps.
|
||||||
// If you press next and then prev too fast you still lock yourself out
|
// If you press next and then prev too fast you still lock yourself out
|
||||||
@@ -136,6 +137,27 @@ func (s *Server) LoadCurr() {
|
|||||||
fmt.Println("Loaded current")
|
fmt.Println("Loaded current")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) LoadThumbnail(mangaId int) (path string, err error) {
|
||||||
|
strId := strconv.Itoa(mangaId)
|
||||||
|
|
||||||
|
s.Mutex.Lock()
|
||||||
|
defer s.Mutex.Unlock()
|
||||||
|
if s.ImageBuffers[strId] != nil {
|
||||||
|
return strId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err := s.Provider.GetThumbnail(strconv.Itoa(mangaId))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
ram, err := addFileToRam(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
s.ImageBuffers[strId] = ram
|
||||||
|
return strId, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) AppendImagesToBuf(html string) ([]view.Image, error) {
|
func (s *Server) AppendImagesToBuf(html string) ([]view.Image, error) {
|
||||||
imgList, err := s.Provider.GetImageList(html)
|
imgList, err := s.Provider.GetImageList(html)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -34,12 +34,52 @@
|
|||||||
.button-36 {
|
.button-36 {
|
||||||
padding: 0 2.6rem;
|
padding: 0 2.6rem;
|
||||||
}
|
}
|
||||||
|
.button-delete{
|
||||||
|
padding: 0 2.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-delete{
|
||||||
|
background-image: linear-gradient(92.88deg, #f44336 9.16%, #f44336 43.89%, #f44336 64.72%);
|
||||||
|
border-radius: 8px;
|
||||||
|
border-style: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #FFFFFF;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-family: "Inter UI","SF Pro Display",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
height: 4rem;
|
||||||
|
padding: 0 1.6rem;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.25) 0 3px 8px;
|
||||||
|
transition: all .5s;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-delete:hover {
|
||||||
|
box-shadow: rgba(244, 67, 54, 0.5) 0 1px 30px;
|
||||||
|
transition-duration: .1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-left{
|
.table-left{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thumbnail{
|
||||||
|
border: 1px solid #ddd; /* Gray border */
|
||||||
|
border-radius: 4px; /* Rounded border */
|
||||||
|
padding: 5px; /* Some padding */
|
||||||
|
width: 150px; /* Set a small width */
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail:hover{
|
||||||
|
box-shadow: 0 0 2px 1px rgba(0, 140, 186, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -54,27 +94,45 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form method="post" action="/new/">
|
<form method="post" action="/new/">
|
||||||
{{/* <label>New Sub Url</label>*/}}
|
|
||||||
<label>
|
<label>
|
||||||
New Sub Url
|
New Sub Url
|
||||||
<input type="text" name="subUrl">
|
<input type="text" name="subUrl">
|
||||||
</label>
|
</label>
|
||||||
<input type="submit" class="button-36">
|
<input type="submit" value="Open" class="button-36">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Thumbnail</th>
|
||||||
<th class="table-left">Title</th>
|
<th class="table-left">Title</th>
|
||||||
<th>Current Chapter</th>
|
<th>Current Chapter</th>
|
||||||
<th>Last Accessed</th>
|
<th>Last Accessed</th>
|
||||||
<th>Link</th>
|
<th>Link</th>
|
||||||
|
<th>Delete</th>
|
||||||
</tr>
|
</tr>
|
||||||
{{range .Mangas}}
|
{{range .Mangas}}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a target="_blank" href="/img/{{.ThumbnailUrl}}">
|
||||||
|
<img class="thumbnail" src="/img/{{.ThumbnailUrl}}" alt="img_{{.ThumbnailUrl}}"/>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td class="table-left">{{.Title}}</td>
|
<td class="table-left">{{.Title}}</td>
|
||||||
<td>{{.Number}}</td>
|
<td>{{.Number}}</td>
|
||||||
<td>{{.LastTime}}</td>
|
<td>{{.LastTime}}</td>
|
||||||
<td><a href="/new/{{.Url}}}" class="button-36">Go to last Chapter</a></td>
|
<td>
|
||||||
|
<a href="/new/{{.Url}}}">
|
||||||
|
<button class="button-36">
|
||||||
|
To chapter
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form method="post" action="/delete">
|
||||||
|
<input type="hidden" name="mangaId" value="{{.ID}}">
|
||||||
|
<input type="submit" class="button-delete" value="Delete">
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ type ImageViewModel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MangaViewModel struct {
|
type MangaViewModel struct {
|
||||||
|
ID int
|
||||||
Title string
|
Title string
|
||||||
Number int
|
Number int
|
||||||
LastTime string
|
LastTime string
|
||||||
Url string
|
Url string
|
||||||
|
ThumbnailUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
type MenuViewModel struct {
|
type MenuViewModel struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user