Made Menu look a bit nicer, added function to add new Manga. Extracted Handler functions to handler.go, fixed bug where new Title would crash
This commit is contained in:
11
Makefile
Normal file
11
Makefile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
run: develop
|
||||||
|
bin/develop
|
||||||
|
|
||||||
|
develop:
|
||||||
|
go build -tags Develop -o bin/develop cmd/mangaGetter/main.go
|
||||||
|
|
||||||
|
release:
|
||||||
|
go build -o bin/MangaGetter_unix cmd/mangaGetter/main.go
|
||||||
|
|
||||||
|
win-amd64:
|
||||||
|
GOOS=windows GOARCH=amd64 go build -o bin/MangaGetter-amd64_windows.exe cmd/mangaGetter/main.go
|
||||||
@@ -39,6 +39,7 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
http.HandleFunc("/", s.HandleMenu)
|
http.HandleFunc("/", s.HandleMenu)
|
||||||
|
http.HandleFunc("/new/", s.HandleNewQuery)
|
||||||
http.HandleFunc("/new/title/{title}/{chapter}", s.HandleNew)
|
http.HandleFunc("/new/title/{title}/{chapter}", s.HandleNew)
|
||||||
http.HandleFunc("/current/", s.HandleCurrent)
|
http.HandleFunc("/current/", s.HandleCurrent)
|
||||||
http.HandleFunc("/img/{url}/", s.HandleImage)
|
http.HandleFunc("/img/{url}/", s.HandleImage)
|
||||||
|
|||||||
229
internal/server/handler.go
Normal file
229
internal/server/handler.go
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"cmp"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"html/template"
|
||||||
|
"mangaGetter/internal/database"
|
||||||
|
"mangaGetter/internal/view"
|
||||||
|
"net/http"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) HandleNew(w http.ResponseWriter, r *http.Request) {
|
||||||
|
title := r.PathValue("title")
|
||||||
|
chapter := r.PathValue("chapter")
|
||||||
|
|
||||||
|
url := fmt.Sprintf("/title/%s/%s", title, chapter)
|
||||||
|
|
||||||
|
s.Mutex.Lock()
|
||||||
|
s.ImageBuffers = make(map[string]*bytes.Buffer)
|
||||||
|
s.Mutex.Unlock()
|
||||||
|
s.CurrSubUrl = url
|
||||||
|
s.PrevSubUrl = ""
|
||||||
|
s.NextSubUrl = ""
|
||||||
|
s.LoadCurr()
|
||||||
|
|
||||||
|
go s.LoadNext()
|
||||||
|
go s.LoadPrev()
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
tmpl := template.Must(view.GetViewTemplate(view.Menu))
|
||||||
|
|
||||||
|
s.DbMgr.Rw.Lock()
|
||||||
|
defer s.DbMgr.Rw.Unlock()
|
||||||
|
|
||||||
|
all := s.DbMgr.Mangas
|
||||||
|
l := len(all)
|
||||||
|
mangaViewModels := make([]view.MangaViewModel, l)
|
||||||
|
counter := 0
|
||||||
|
|
||||||
|
for _, manga := range all {
|
||||||
|
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
||||||
|
|
||||||
|
mangaViewModels[counter] = view.MangaViewModel{
|
||||||
|
Title: title,
|
||||||
|
Number: manga.LatestChapter.Number,
|
||||||
|
// 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)"),
|
||||||
|
Url: manga.LatestChapter.Url,
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.SortStableFunc(mangaViewModels, func(a, b view.MangaViewModel) int {
|
||||||
|
return cmp.Compare(a.Title, b.Title)
|
||||||
|
})
|
||||||
|
|
||||||
|
menuViewModel := view.MenuViewModel{
|
||||||
|
Mangas: mangaViewModels,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := tmpl.Execute(w, menuViewModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := s.DbMgr.Save()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
tmpl := template.Must(view.GetViewTemplate(view.Viewer))
|
||||||
|
|
||||||
|
s.DbMgr.Rw.Lock()
|
||||||
|
defer s.DbMgr.Rw.Unlock()
|
||||||
|
|
||||||
|
mangaId, chapterId, err := s.Provider.GetTitleIdAndChapterId(s.CurrSubUrl)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
title, chapter, err := s.Provider.GetTitleAndChapter(s.CurrSubUrl)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
var manga *database.Manga
|
||||||
|
if s.DbMgr.Mangas[mangaId] == nil {
|
||||||
|
manga = &database.Manga{
|
||||||
|
Id: mangaId,
|
||||||
|
Title: title,
|
||||||
|
TimeStampUnix: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
s.DbMgr.Mangas[mangaId] = manga
|
||||||
|
} else {
|
||||||
|
manga = s.DbMgr.Mangas[mangaId]
|
||||||
|
s.DbMgr.Mangas[mangaId].TimeStampUnix = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.DbMgr.Chapters[chapterId] == nil {
|
||||||
|
chapterNumberStr := strings.Replace(chapter, "ch_", "", 1)
|
||||||
|
number, err := strconv.Atoi(chapterNumberStr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
number = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
s.DbMgr.Chapters[chapterId] = &database.Chapter{
|
||||||
|
Id: chapterId,
|
||||||
|
Manga: manga,
|
||||||
|
Url: s.CurrSubUrl,
|
||||||
|
Name: chapter,
|
||||||
|
Number: number,
|
||||||
|
TimeStampUnix: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.DbMgr.Chapters[chapterId].TimeStampUnix = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.DbMgr.Mangas[mangaId].LatestChapter = s.DbMgr.Chapters[chapterId]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tmpl.Execute(w, s.CurrViewModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleImage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
u := r.PathValue("url")
|
||||||
|
s.Mutex.Lock()
|
||||||
|
buf := s.ImageBuffers[u]
|
||||||
|
if buf == nil {
|
||||||
|
fmt.Printf("url: %s is nil\n", u)
|
||||||
|
w.WriteHeader(400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "image/webp")
|
||||||
|
_, err := w.Write(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
s.Mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Println("Received Next")
|
||||||
|
|
||||||
|
if s.PrevViewModel != nil {
|
||||||
|
go func(viewModel view.ImageViewModel, s *Server) {
|
||||||
|
s.Mutex.Lock()
|
||||||
|
for _, img := range viewModel.Images {
|
||||||
|
delete(s.ImageBuffers, img.Path)
|
||||||
|
}
|
||||||
|
s.Mutex.Unlock()
|
||||||
|
fmt.Println("Cleaned out of scope Last")
|
||||||
|
}(*s.PrevViewModel, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.PrevViewModel = s.CurrViewModel
|
||||||
|
s.CurrViewModel = s.NextViewModel
|
||||||
|
s.PrevSubUrl = s.CurrSubUrl
|
||||||
|
s.CurrSubUrl = s.NextSubUrl
|
||||||
|
|
||||||
|
<-s.NextReady
|
||||||
|
|
||||||
|
go s.LoadNext()
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Println("Received Prev")
|
||||||
|
if s.NextViewModel != nil {
|
||||||
|
go func(viewModel view.ImageViewModel, s *Server) {
|
||||||
|
s.Mutex.Lock()
|
||||||
|
for _, img := range viewModel.Images {
|
||||||
|
delete(s.ImageBuffers, img.Path)
|
||||||
|
}
|
||||||
|
s.Mutex.Unlock()
|
||||||
|
fmt.Println("Cleaned out of scope Last")
|
||||||
|
}(*s.NextViewModel, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.NextViewModel = s.CurrViewModel
|
||||||
|
s.CurrViewModel = s.PrevViewModel
|
||||||
|
s.NextSubUrl = s.CurrSubUrl
|
||||||
|
s.CurrSubUrl = s.PrevSubUrl
|
||||||
|
|
||||||
|
<-s.PrevReady
|
||||||
|
|
||||||
|
go s.LoadPrev()
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) {
|
||||||
|
sub := r.PostFormValue("subUrl")
|
||||||
|
|
||||||
|
url := fmt.Sprintf("/title/%s", sub)
|
||||||
|
|
||||||
|
s.Mutex.Lock()
|
||||||
|
s.ImageBuffers = make(map[string]*bytes.Buffer)
|
||||||
|
s.Mutex.Unlock()
|
||||||
|
s.CurrSubUrl = url
|
||||||
|
s.PrevSubUrl = ""
|
||||||
|
s.NextSubUrl = ""
|
||||||
|
s.LoadCurr()
|
||||||
|
|
||||||
|
go s.LoadNext()
|
||||||
|
go s.LoadPrev()
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
@@ -3,20 +3,14 @@ package server
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/text/language"
|
|
||||||
"html/template"
|
|
||||||
"io"
|
"io"
|
||||||
"mangaGetter/internal/database"
|
"mangaGetter/internal/database"
|
||||||
"mangaGetter/internal/provider"
|
"mangaGetter/internal/provider"
|
||||||
"mangaGetter/internal/view"
|
"mangaGetter/internal/view"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/text/cases"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
@@ -44,50 +38,6 @@ type Server struct {
|
|||||||
PrevReady chan bool
|
PrevReady chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleImage(w http.ResponseWriter, r *http.Request) {
|
|
||||||
u := r.PathValue("url")
|
|
||||||
s.Mutex.Lock()
|
|
||||||
buf := s.ImageBuffers[u]
|
|
||||||
if buf == nil {
|
|
||||||
fmt.Printf("url: %s is nil\n", u)
|
|
||||||
w.WriteHeader(400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "image/webp")
|
|
||||||
_, err := w.Write(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
s.Mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Println("Received Next")
|
|
||||||
|
|
||||||
if s.PrevViewModel != nil {
|
|
||||||
go func(viewModel view.ImageViewModel, s *Server) {
|
|
||||||
s.Mutex.Lock()
|
|
||||||
for _, img := range viewModel.Images {
|
|
||||||
delete(s.ImageBuffers, img.Path)
|
|
||||||
}
|
|
||||||
s.Mutex.Unlock()
|
|
||||||
fmt.Println("Cleaned out of scope Last")
|
|
||||||
}(*s.PrevViewModel, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.PrevViewModel = s.CurrViewModel
|
|
||||||
s.CurrViewModel = s.NextViewModel
|
|
||||||
s.PrevSubUrl = s.CurrSubUrl
|
|
||||||
s.CurrSubUrl = s.NextSubUrl
|
|
||||||
|
|
||||||
<-s.NextReady
|
|
||||||
|
|
||||||
go s.LoadNext()
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) LoadNext() {
|
func (s *Server) LoadNext() {
|
||||||
c, err := s.Provider.GetHtml(s.CurrSubUrl)
|
c, err := s.Provider.GetHtml(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -166,106 +116,6 @@ func (s *Server) LoadPrev() {
|
|||||||
s.PrevReady <- true
|
s.PrevReady <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Println("Received Prev")
|
|
||||||
if s.NextViewModel != nil {
|
|
||||||
go func(viewModel view.ImageViewModel, s *Server) {
|
|
||||||
s.Mutex.Lock()
|
|
||||||
for _, img := range viewModel.Images {
|
|
||||||
delete(s.ImageBuffers, img.Path)
|
|
||||||
}
|
|
||||||
s.Mutex.Unlock()
|
|
||||||
fmt.Println("Cleaned out of scope Last")
|
|
||||||
}(*s.NextViewModel, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.NextViewModel = s.CurrViewModel
|
|
||||||
s.CurrViewModel = s.PrevViewModel
|
|
||||||
s.NextSubUrl = s.CurrSubUrl
|
|
||||||
s.CurrSubUrl = s.PrevSubUrl
|
|
||||||
|
|
||||||
<-s.PrevReady
|
|
||||||
|
|
||||||
go s.LoadPrev()
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleCurrent(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
tmpl := template.Must(view.GetViewTemplate(view.Viewer))
|
|
||||||
|
|
||||||
s.DbMgr.Rw.Lock()
|
|
||||||
defer s.DbMgr.Rw.Unlock()
|
|
||||||
|
|
||||||
mangaId, chapterId, err := s.Provider.GetTitleIdAndChapterId(s.CurrSubUrl)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
title, chapter, err := s.Provider.GetTitleAndChapter(s.CurrSubUrl)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
var manga *database.Manga
|
|
||||||
if s.DbMgr.Mangas[mangaId] == nil {
|
|
||||||
manga = &database.Manga{
|
|
||||||
Id: mangaId,
|
|
||||||
Title: title,
|
|
||||||
TimeStampUnix: time.Now().Unix(),
|
|
||||||
}
|
|
||||||
s.DbMgr.Mangas[mangaId] = manga
|
|
||||||
} else {
|
|
||||||
manga = s.DbMgr.Mangas[mangaId]
|
|
||||||
s.DbMgr.Mangas[mangaId].TimeStampUnix = time.Now().Unix()
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.DbMgr.Chapters[chapterId] == nil {
|
|
||||||
chapterNumberStr := strings.Replace(chapter, "ch_", "", 1)
|
|
||||||
number, err := strconv.Atoi(chapterNumberStr)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
number = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
s.DbMgr.Chapters[chapterId] = &database.Chapter{
|
|
||||||
Id: chapterId,
|
|
||||||
Manga: manga,
|
|
||||||
Url: s.CurrSubUrl,
|
|
||||||
Name: chapter,
|
|
||||||
Number: number,
|
|
||||||
TimeStampUnix: time.Now().Unix(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s.DbMgr.Chapters[chapterId].TimeStampUnix = time.Now().Unix()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tmpl.Execute(w, s.CurrViewModel)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleNew(w http.ResponseWriter, r *http.Request) {
|
|
||||||
title := r.PathValue("title")
|
|
||||||
chapter := r.PathValue("chapter")
|
|
||||||
|
|
||||||
url := fmt.Sprintf("/title/%s/%s", title, chapter)
|
|
||||||
|
|
||||||
s.Mutex.Lock()
|
|
||||||
s.ImageBuffers = make(map[string]*bytes.Buffer)
|
|
||||||
s.Mutex.Unlock()
|
|
||||||
s.CurrSubUrl = url
|
|
||||||
s.PrevSubUrl = ""
|
|
||||||
s.NextSubUrl = ""
|
|
||||||
s.LoadCurr()
|
|
||||||
|
|
||||||
go s.LoadNext()
|
|
||||||
go s.LoadPrev()
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) LoadCurr() {
|
func (s *Server) LoadCurr() {
|
||||||
html, err := s.Provider.GetHtml(s.CurrSubUrl)
|
html, err := s.Provider.GetHtml(s.CurrSubUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -315,50 +165,6 @@ func (s *Server) AppendImagesToBuf(html string) ([]view.Image, error) {
|
|||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
tmpl := template.Must(view.GetViewTemplate(view.Menu))
|
|
||||||
|
|
||||||
s.DbMgr.Rw.Lock()
|
|
||||||
defer s.DbMgr.Rw.Unlock()
|
|
||||||
|
|
||||||
all := s.DbMgr.Mangas
|
|
||||||
l := len(all)
|
|
||||||
mangaViewModels := make([]view.MangaViewModel, l)
|
|
||||||
counter := 0
|
|
||||||
|
|
||||||
for _, manga := range all {
|
|
||||||
title := cases.Title(language.English, cases.Compact).String(strings.Replace(manga.Title, "-", " ", -1))
|
|
||||||
|
|
||||||
mangaViewModels[counter] = view.MangaViewModel{
|
|
||||||
Title: title,
|
|
||||||
Number: manga.LatestChapter.Number,
|
|
||||||
// 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)"),
|
|
||||||
Url: manga.LatestChapter.Url,
|
|
||||||
}
|
|
||||||
counter++
|
|
||||||
}
|
|
||||||
|
|
||||||
menuViewModel := view.MenuViewModel{
|
|
||||||
Mangas: mangaViewModels,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := tmpl.Execute(w, menuViewModel)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
err := s.DbMgr.Save()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addFileToRam(url string) (*bytes.Buffer, error) {
|
func addFileToRam(url string) (*bytes.Buffer, error) {
|
||||||
// Get the data
|
// Get the data
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
|
|||||||
@@ -3,19 +3,80 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Main Menu</title>
|
<title>Main Menu</title>
|
||||||
|
<style>
|
||||||
|
.button-36 {
|
||||||
|
background-image: linear-gradient(92.88deg, #455EB5 9.16%, #5643CC 43.89%, #673FD7 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-36:hover {
|
||||||
|
box-shadow: rgba(80, 63, 205, 0.5) 0 1px 30px;
|
||||||
|
transition-duration: .1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.button-36 {
|
||||||
|
padding: 0 2.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-left{
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form method="post" action="/new/">
|
<form method="post" action="/new/">
|
||||||
|
{{/* <label>New Sub Url</label>*/}}
|
||||||
|
<label>
|
||||||
|
New Sub Url
|
||||||
|
<input type="text" name="subUrl">
|
||||||
|
</label>
|
||||||
|
<input type="submit" class="button-36">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{range .Mangas}}
|
<table class="table">
|
||||||
<div>
|
<tr>
|
||||||
<text>Title: {{.Title}}</text>
|
<th class="table-left">Title</th>
|
||||||
<text>Current Chapter: {{.Number}}</text>
|
<th>Current Chapter</th>
|
||||||
<text>Last Accessed: {{.LastTime}}</text>
|
<th>Last Accessed</th>
|
||||||
<a href="/new/{{.Url}}}" class="button">Go to last Chapter</a>
|
<th>Link</th>
|
||||||
</div>
|
</tr>
|
||||||
{{end}}
|
{{range .Mangas}}
|
||||||
|
<tr>
|
||||||
|
<td class="table-left">{{.Title}}</td>
|
||||||
|
<td>{{.Number}}</td>
|
||||||
|
<td>{{.LastTime}}</td>
|
||||||
|
<td><a href="/new/{{.Url}}}" class="button-36">Go to last Chapter</a></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user