mirror of
https://github.com/rystaf/mlmym.git
synced 2024-11-05 06:43:21 +00:00
parent
08a7ec66d4
commit
34f349313f
|
@ -253,9 +253,12 @@ summary {
|
|||
border-top: 1px dotted gray;
|
||||
font-size: 12px;
|
||||
}
|
||||
.comment form.savecomment {
|
||||
form.savecomment {
|
||||
margin: 0px 0px 10px 10px;
|
||||
}
|
||||
.comment > .children > form.savecomment {
|
||||
margin: 0px 0px 10px 20px;
|
||||
}
|
||||
.savecomment textarea {
|
||||
width: 500px;
|
||||
height: 100px;
|
||||
|
@ -370,7 +373,6 @@ form.nsfw div {
|
|||
}
|
||||
.pager {
|
||||
margin: 10px;
|
||||
display: none;
|
||||
}
|
||||
.pager a {
|
||||
padding: 1px 4px;
|
||||
|
@ -381,10 +383,18 @@ form.nsfw div {
|
|||
text-decoration: none;
|
||||
color: #369;
|
||||
}
|
||||
.pager.hidden {
|
||||
display: none;
|
||||
}
|
||||
#loadmore {
|
||||
display: none;
|
||||
}
|
||||
#loadmore, #end {
|
||||
visibility: hidden;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
#loadmore.show {
|
||||
display: block;
|
||||
}
|
||||
#loadmore[disabled] {
|
||||
visibility: visible;
|
||||
}
|
||||
|
@ -475,6 +485,23 @@ form.nsfw div {
|
|||
position: relative;
|
||||
color: #000;
|
||||
}
|
||||
#settings {
|
||||
background-color: white;
|
||||
border: 1px solid #888;
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 45px;
|
||||
}
|
||||
#settings form {
|
||||
margin: 0px;
|
||||
}
|
||||
.dark #settings {
|
||||
background-color: #262626;
|
||||
}
|
||||
#settings.open {
|
||||
display: inline-block;
|
||||
}
|
||||
.expando.open{
|
||||
display: block;
|
||||
}
|
||||
|
@ -980,7 +1007,7 @@ form.create input[type=file], form.create select {
|
|||
}
|
||||
.preferences label{
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
function request(url, params, callback, errorcallback) {
|
||||
function request(url, params, callback, errorcallback = function(){}) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = function() {
|
||||
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
|
||||
if (xmlHttp.readyState != 4 ) { return }
|
||||
if (xmlHttp.status == 200) {
|
||||
return callback(xmlHttp.responseText);
|
||||
}
|
||||
errorcallback(xmlHttp.responseText);
|
||||
}
|
||||
var method = "GET"
|
||||
|
@ -41,7 +43,11 @@ function commentClick(e) {
|
|||
var form = e.target.parentNode
|
||||
if (form) {
|
||||
data = new FormData(form)
|
||||
if (("c"+data.get("commentid")) != targ.id) { return }
|
||||
if (("c"+data.get("commentid")) == targ.id) {
|
||||
|
||||
} else if (("c"+data.get("parentid")) == targ.id) {
|
||||
targ = form
|
||||
} else { return }
|
||||
params = new URLSearchParams(data).toString()
|
||||
params += "&" + e.target.name + "=" + e.target.value
|
||||
params += "&xhr=1"
|
||||
|
@ -114,6 +120,8 @@ function loadMore(e) {
|
|||
toggle_images(true)
|
||||
}
|
||||
}
|
||||
var loadmore = document.getElementById("loadmore")
|
||||
if (loadmore) loadmore.className = "show"
|
||||
}
|
||||
else {
|
||||
e.target.outerHTML = '<input id="end" type="submit" value="" disabled>'
|
||||
|
@ -167,6 +175,47 @@ function formSubmit(e) {
|
|||
return false
|
||||
}
|
||||
|
||||
function open_settings(e) {
|
||||
e.preventDefault()
|
||||
var settings = document.getElementById("settings")
|
||||
settings.className = "open"
|
||||
request(e.target.href + "?xhr=1", "", function(res) {
|
||||
settings.innerHTML = res
|
||||
var options = document.getElementsByClassName("scripting")
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var input = options[i].getElementsByTagName('input')
|
||||
if (!input.length) { continue }
|
||||
if (localStorage.getItem(input[0].name) == "true") {
|
||||
input[0].checked = "checked"
|
||||
}
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
function close_settings(e) {
|
||||
e.preventDefault()
|
||||
var settings = document.getElementById("settings")
|
||||
settings.className = ""
|
||||
return false
|
||||
}
|
||||
|
||||
function save_settings(e) {
|
||||
e = e || window.event;
|
||||
var targ = e.currentTarget || e.srcElement || e;
|
||||
var data = new FormData(targ)
|
||||
console.log(data)
|
||||
e.preventDefault()
|
||||
var params = new URLSearchParams(data).toString()
|
||||
request(targ.target, params, function(res) {
|
||||
["endlessScrolling", "autoLoad"].map(function(x) {
|
||||
localStorage.setItem(x, data.get(x)=="on")
|
||||
})
|
||||
window.location.reload()
|
||||
})
|
||||
return false;
|
||||
}
|
||||
|
||||
function parse_youtube(url){
|
||||
if (url.indexOf("youtu") == -1) return false
|
||||
var regExp = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/|shorts\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/;
|
||||
|
@ -227,12 +276,22 @@ for (var i = 0; i < posts.length; i++) {
|
|||
}
|
||||
}
|
||||
|
||||
window.onscroll = function(ev) {
|
||||
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
|
||||
var loadmore = document.getElementById("loadmore")
|
||||
if (loadmore) {
|
||||
loadmore.click()
|
||||
}
|
||||
}
|
||||
};
|
||||
if (localStorage.getItem("endlessScrolling") == "true") {
|
||||
var pager = document.getElementsByClassName("pager")
|
||||
if (pager.length) pager[0].className = "pager hidden"
|
||||
var loadmore = document.getElementById("loadmore")
|
||||
if (loadmore) loadmore.className = "show"
|
||||
|
||||
if (localStorage.getItem("autoLoad") == "true") {
|
||||
window.onscroll = function(e) {
|
||||
if ((window.innerHeight + Math.round(window.scrollY)) >= document.body.offsetHeight) {
|
||||
var loadmore = document.getElementById("loadmore")
|
||||
if (loadmore) {
|
||||
loadmore.click()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
74
routes.go
74
routes.go
|
@ -147,7 +147,7 @@ var funcMap = template.FuncMap{
|
|||
converted = re.ReplaceAllString(converted, `href="/`+host+`/$1`)
|
||||
re = regexp.MustCompile(` !([a-zA-Z0-9]+)@([a-zA-Z0-9\.\-]+) `)
|
||||
converted = re.ReplaceAllString(converted, ` <a href="/$2/c/$1">!$1@$2</a> `)
|
||||
re = regexp.MustCompile(`::: spoiler (.*?)\n(.*?)\s:::`)
|
||||
re = regexp.MustCompile(`::: spoiler (.*?)\n([\S\s]*?):::`)
|
||||
converted = re.ReplaceAllString(converted, "<details><summary>$1</summary>$2</details>")
|
||||
return template.HTML(converted)
|
||||
},
|
||||
|
@ -999,33 +999,59 @@ func UserOp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
parentid, _ := strconv.Atoi(r.FormValue("parentid"))
|
||||
state.GetComment(parentid)
|
||||
}
|
||||
createComment := types.CreateComment{
|
||||
Content: r.FormValue("content"),
|
||||
PostID: state.PostID,
|
||||
if r.FormValue("submit") == "save" {
|
||||
createComment := types.CreateComment{
|
||||
Content: r.FormValue("content"),
|
||||
PostID: state.PostID,
|
||||
}
|
||||
if state.CommentID > 0 {
|
||||
createComment.ParentID = types.NewOptional(state.CommentID)
|
||||
}
|
||||
resp, err := state.Client.CreateComment(context.Background(), createComment)
|
||||
if err == nil {
|
||||
if r.FormValue("xhr") != "" {
|
||||
state.XHR = true
|
||||
state.Comments = nil
|
||||
state.GetComment(resp.CommentView.Comment.ID)
|
||||
Render(w, "index.html", state)
|
||||
return
|
||||
}
|
||||
postid := strconv.Itoa(state.PostID)
|
||||
commentid := strconv.Itoa(resp.CommentView.Comment.ID)
|
||||
r.URL.Path = "/" + state.Host + "/post/" + postid
|
||||
r.URL.Fragment = "c" + commentid
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else if r.FormValue("xhr") != "" {
|
||||
w.Write([]byte{})
|
||||
return
|
||||
}
|
||||
if state.CommentID > 0 {
|
||||
createComment.ParentID = types.NewOptional(state.CommentID)
|
||||
}
|
||||
resp, err := state.Client.CreateComment(context.Background(), createComment)
|
||||
if err == nil {
|
||||
postid := strconv.Itoa(state.PostID)
|
||||
commentid := strconv.Itoa(resp.CommentView.Comment.ID)
|
||||
r.URL.Path = "/" + state.Host + "/post/" + postid
|
||||
r.URL.Fragment = "c" + commentid
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
if r.FormValue("submit") == "cancel" {
|
||||
r.URL.RawQuery = ""
|
||||
}
|
||||
case "edit_comment":
|
||||
commentid, _ := strconv.Atoi(r.FormValue("commentid"))
|
||||
resp, err := state.Client.EditComment(context.Background(), types.EditComment{
|
||||
CommentID: commentid,
|
||||
Content: types.NewOptional(r.FormValue("content")),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
commentid := strconv.Itoa(resp.CommentView.Comment.ID)
|
||||
r.URL.Fragment = "c" + commentid
|
||||
if r.FormValue("submit") == "save" {
|
||||
resp, err := state.Client.EditComment(context.Background(), types.EditComment{
|
||||
CommentID: commentid,
|
||||
Content: types.NewOptional(r.FormValue("content")),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
commentid := strconv.Itoa(resp.CommentView.Comment.ID)
|
||||
r.URL.Fragment = "c" + commentid
|
||||
r.URL.RawQuery = ""
|
||||
}
|
||||
}
|
||||
if r.FormValue("xhr") != "" {
|
||||
state.XHR = true
|
||||
state.GetComment(commentid)
|
||||
Render(w, "index.html", state)
|
||||
return
|
||||
}
|
||||
if r.FormValue("submit") == "cancel" {
|
||||
r.URL.RawQuery = ""
|
||||
}
|
||||
case "delete_comment":
|
||||
|
|
|
@ -28,17 +28,25 @@
|
|||
{{ end }}
|
||||
</div>
|
||||
{{ if eq .Op "edit" }}
|
||||
<div class="content">
|
||||
<form class="savecomment" method="POST">
|
||||
<div>
|
||||
<textarea required name="content">{{ .P.Comment.Content }}</textarea>
|
||||
</div>
|
||||
<input type="hidden" name="commentid" value="{{.P.Comment.ID}}">
|
||||
<input type="hidden" name="op" value="edit_comment">
|
||||
<input type="submit" value="save">
|
||||
<input name="submit" type="submit" value="save">
|
||||
<input name="submit" type="submit" value="cancel">
|
||||
</form>
|
||||
{{ else }}
|
||||
<div class="content{{ if and .Selected}} highlight{{end}}">
|
||||
{{if .P.Comment.Deleted}}[removed]{{else}}{{ markdown .State.Host .P.Comment.Content }}{{end}}
|
||||
<div class="content">
|
||||
{{if .P.Comment.Deleted}}
|
||||
[removed]
|
||||
{{else}}
|
||||
<div {{ if and .Selected (not .State.XHR) (ne .State.Op "reply")}}class="highlight" {{end}}>
|
||||
{{ markdown .State.Host .P.Comment.Content }}
|
||||
</div>
|
||||
{{end}}
|
||||
{{ if eq .Op "source" }}
|
||||
<div><textarea>{{.P.Comment.Content}}</textarea></div>
|
||||
{{end}}
|
||||
|
@ -73,13 +81,11 @@
|
|||
{{ end }}
|
||||
</form>
|
||||
</li>
|
||||
{{ if ne .Op "reply" }}
|
||||
<li>
|
||||
<a class="reply" for="c{{.P.Comment.ID}}" href="/{{.State.Host}}/comment/{{.P.Comment.ID}}?reply">
|
||||
reply
|
||||
</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if gt .ChildCount 0 }}
|
||||
<li><a class="hidechildren" for="c{{.P.Comment.ID}}" href=""><span class="hide">hide</span><span class="show">show {{ .ChildCount }}</span> child comments</a></li>
|
||||
|
@ -90,11 +96,12 @@
|
|||
{{ if and (eq .State.Op "reply") (eq .State.CommentID .P.Comment.ID)}}
|
||||
<form class="savecomment" method="POST">
|
||||
<div>
|
||||
<textarea required name="content"></textarea>
|
||||
<textarea name="content"></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="parentid" value="{{.P.Comment.ID}}">
|
||||
<input type="hidden" name="op" value="create_comment">
|
||||
<input type="submit" value="save">
|
||||
<input type="submit" name="submit" value="save">
|
||||
<input type="submit" name="submit" value="cancel">
|
||||
</form>
|
||||
{{ end}}
|
||||
{{ range $ci, $child := .C }}{{ template "comment.html" $child }}{{end}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<head>
|
||||
<title>{{ if and .Community (ne .Community.CommunityView.Community.Title "")}}{{.Community.CommunityView.Community.Title}}{{else if ne .CommunityName ""}}/c/{{.CommunityName}}{{ else if .User}}overview for {{.User.PersonView.Person.Name}}{{else}}{{ host .Host }}{{end}}</title>
|
||||
<link rel="shortcut icon" href="/{{.Host}}/icon.jpg">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=14">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=15">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body {{ if .Dark }}class="dark"{{end}}>
|
||||
|
@ -56,6 +56,6 @@
|
|||
{{ template "sidebar.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
<script src="/_/static/utils.js?v=7"></script>
|
||||
<script src="/_/static/utils.js?v=9"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,21 +3,18 @@
|
|||
<title>{{if and .Posts .PostID }}{{ (index .Posts 0).Post.Name}} : {{.CommunityName}}{{else if and .Community (ne .Community.CommunityView.Community.Title "")}}{{.Community.CommunityView.Community.Title}}{{else if ne .CommunityName ""}}/c/{{.CommunityName}}{{ else if .User}}overview for {{.User.PersonView.Person.Name}}{{else}}{{ host .Host }}{{end}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="shortcut icon" href="/{{.Host}}/icon.jpg">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=14">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=15">
|
||||
</head>
|
||||
<body{{ if .Dark }} class="dark"{{end}}>
|
||||
<noscript>
|
||||
<style>
|
||||
.scripting,
|
||||
.expando-button,
|
||||
.minimize,
|
||||
#loadmore,
|
||||
#showimages,
|
||||
.hidechildren {
|
||||
display: none !important;
|
||||
}
|
||||
div.pager {
|
||||
display: block;
|
||||
}
|
||||
.post .expando .image img {
|
||||
visibility: visible;
|
||||
}
|
||||
|
@ -99,7 +96,7 @@
|
|||
<textarea required name="content" {{ if (index .Posts 0).Post.Deleted }} disabled {{end}}></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="op" value="create_comment">
|
||||
<input type="submit" value="save"{{ if (index .Posts 0).Post.Deleted }} disabled {{end}}>
|
||||
<input type="submit" name="submit" value="save"{{ if (index .Posts 0).Post.Deleted }} disabled {{end}}>
|
||||
</form>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
@ -128,7 +125,7 @@
|
|||
<input id="loadmore" type="submit" value="load more" onclick="loadMore(event)" data-page="2">
|
||||
{{ end }}
|
||||
|
||||
<script src="/_/static/utils.js?v=7"></script>
|
||||
<script src="/_/static/utils.js?v=9"></script>
|
||||
{{ template "sidebar.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
|
|
||||
<a href="/{{.Host}}/inbox" class="mailbox{{ if .UnreadCount }} orangered{{end}}">✉</a>
|
||||
|
|
||||
<a href="/{{.Host}}/settings">settings</a>
|
||||
<a href="/{{.Host}}/settings" onclick="open_settings(event)">settings</a>
|
||||
|
|
||||
<form method="POST"><input type="submit" name="op" value="logout"></form>
|
||||
{{else}}
|
||||
<a href="/{{.Host}}/login">log in</a> or <a href="/{{.Host}}/login">sign up</a>
|
||||
|
|
||||
<a href="/{{.Host}}/settings">settings</a>
|
||||
<a href="/{{.Host}}/settings" onclick="open_settings(event)">settings</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div id="settings"></div>
|
||||
<div class="spacer">
|
||||
<a href="/{{ .Host}}/">
|
||||
<img class="icon" src="{{ if .Site }}{{ .Site.SiteView.Site.Icon.String }}{{else}}/{{ .Host}}/icon.jpg{{end}}">
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
{{ if not .XHR }}
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>{{ host .Host }}: preferences</title>
|
||||
<link rel="shortcut icon" href="/{{.Host}}/icon.jpg">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=7">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=15">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body {{ if .Dark}}class="dark"{{end}}>
|
||||
<noscript>
|
||||
<style>
|
||||
.scripting {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</noscript>
|
||||
<nav>
|
||||
<div class="communities">
|
||||
<a href="/{{.Host}}">home</a>
|
||||
|
@ -52,7 +60,8 @@
|
|||
{{ if .Error }}
|
||||
<div class="error">{{.Error}}</div>
|
||||
{{ end }}
|
||||
<form class="preferences" method="POST">
|
||||
{{ end }}
|
||||
<form class="preferences" method="POST" target="/{{.Host}}/settings" onsubmit="save_settings(event)" >
|
||||
<div>
|
||||
<label>
|
||||
default listing
|
||||
|
@ -90,11 +99,26 @@
|
|||
</label>
|
||||
<input type="checkbox" name="darkmode" {{ if .Dark }}checked{{end}}>
|
||||
</div>
|
||||
<div class="scripting">
|
||||
<label>
|
||||
endless scrolling
|
||||
</label>
|
||||
<input type="checkbox" name="endlessScrolling">
|
||||
</div>
|
||||
<div class="scripting">
|
||||
<label>
|
||||
auto load more
|
||||
</label>
|
||||
<input type="checkbox" name="autoLoad">
|
||||
</div>
|
||||
<div>
|
||||
<label></label>
|
||||
<input type="submit" value="save">
|
||||
{{ if .XHR }}<input type="submit" value="close" onclick="close_settings(event)">{{ end }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{{ if not .XHR}}
|
||||
<script src="/_/static/utils.js?v=8"></script>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
|
|
Loading…
Reference in a new issue