Compare commits
21 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a96b5b1cd2 | ||
|
|
d8292bb9be | ||
|
|
3e1e3868f4 | ||
|
|
a91b08547b | ||
|
|
624b7e4847 | ||
|
|
c935ffabea | ||
|
|
f5a423f2d5 | ||
|
|
c5a53c79da | ||
|
|
669749c12e | ||
|
|
dd58cb7e55 | ||
|
|
2bea76c7f0 | ||
|
|
a689604470 | ||
|
|
6c80f67535 | ||
|
|
463b3fe49d | ||
|
|
3fe31bd5b3 | ||
|
|
1858f1aec0 | ||
|
|
dd4f76a393 | ||
|
|
f7c2910b07 | ||
|
|
556cc785f5 | ||
|
|
d5a96181d2 | ||
|
|
3ebf9b3793 |
19 changed files with 433 additions and 148 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
mlmym
|
||||
VERSION
|
||||
*.toml
|
||||
*.txt
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ WORKDIR /app
|
|||
COPY go.* ./
|
||||
RUN go mod download
|
||||
COPY . ./
|
||||
RUN git describe --tag > VERSION
|
||||
RUN go build -v -o mlmym
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
|
|
@ -14,4 +15,5 @@ RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -
|
|||
COPY --from=builder /app/mlmym /app/mlmym
|
||||
COPY --from=builder /app/templates /app/templates
|
||||
COPY --from=builder /app/public /app/public
|
||||
COPY --from=builder /app/VERSION /app/VERSION
|
||||
CMD ["./mlmym", "--addr", "0.0.0.0:8080"]
|
||||
|
|
|
|||
23
Makefile
23
Makefile
|
|
@ -1,17 +1,18 @@
|
|||
.PHONY: dev reload serve style
|
||||
.PHONY: dev reload serve VERSION
|
||||
|
||||
all:
|
||||
$(MAKE) -j3 --no-print-directory dev
|
||||
all: mlmym
|
||||
|
||||
dev: reload serve style
|
||||
mlmym: VERSION
|
||||
go build -v -o mlmym
|
||||
|
||||
dev:
|
||||
$(MAKE) -j2 --no-print-directory reload serve
|
||||
|
||||
reload:
|
||||
#websocketd --port=8080 watchexec -w public echo reload &>/dev/null
|
||||
websocketd --loglevel=fatal --port=8009 watchexec --no-vcs-ignore -e html,css,js -d 500 -w public 'echo "$$WATCHEXEC_WRITTEN_PATH"'
|
||||
websocketd --loglevel=fatal --port=8009 watchexec --no-vcs-ignore -e html,css,js 'echo "$$WATCHEXEC_WRITTEN_PATH"'
|
||||
|
||||
serve:
|
||||
#python -m http.server --directory ./public 8081 &>/dev/null
|
||||
DEBUG=true watchexec -e go -r "go run . --addr 0.0.0.0:8008 -w"
|
||||
VERSION:
|
||||
git describe --tag > $@
|
||||
|
||||
style:
|
||||
npm run watchcss > /dev/null 2>&1
|
||||
serve: VERSION
|
||||
DEBUG=true watchexec --no-vcs-ignore -e go -r "go run . --addr 0.0.0.0:8008 -w"
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -3,14 +3,23 @@ a familiar desktop experience for [lemmy](https://join-lemmy.org).
|
|||
|
||||

|
||||
|
||||
### deployment
|
||||
## deployment
|
||||
|
||||
```bash
|
||||
docker run -it -p "8080:8080" ghcr.io/rystaf/mlmym:latest
|
||||
```
|
||||
|
||||
### config
|
||||
## config
|
||||
Set the environment variable `LEMMY_DOMAIN` to run in single instance mode
|
||||
```bash
|
||||
docker run -it -e LEMMY_DOMAIN='lemmydomain.com' -p "8080:8080" ghcr.io/rystaf/mlmym:latest
|
||||
```
|
||||
#### default user settings
|
||||
| environment variable | default |
|
||||
| -------------------- | ------- |
|
||||
| DARK | false |
|
||||
| HIDE_THUMBNAILS | false |
|
||||
| LISTING | All |
|
||||
| SORT | Hot |
|
||||
| COMMENT_SORT | Hot |
|
||||
|
||||
|
|
|
|||
7
main.go
7
main.go
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/yuin/goldmark/extension"
|
||||
)
|
||||
|
||||
var version string
|
||||
var watch = flag.Bool("w", false, "watch for file changes")
|
||||
var addr = flag.String("addr", ":80", "http service address")
|
||||
var md goldmark.Markdown
|
||||
|
|
@ -55,7 +56,7 @@ func init() {
|
|||
))
|
||||
templates = make(map[string]*template.Template)
|
||||
if !*watch {
|
||||
for _, name := range []string{"index.html", "login.html", "frontpage.html", "root.html", "settings.html", "xhr.html"} {
|
||||
for _, name := range []string{"index.html", "login.html", "frontpage.html", "root.html", "settings.html", "xhr.html", "create_comment.html"} {
|
||||
t := template.New(name).Funcs(funcMap)
|
||||
glob, err := t.ParseGlob("templates/*")
|
||||
if err != nil {
|
||||
|
|
@ -68,6 +69,9 @@ func init() {
|
|||
if os.Getenv("DEBUG") != "" {
|
||||
test()
|
||||
}
|
||||
if data, err := os.ReadFile("VERSION"); err == nil {
|
||||
version = string(data)
|
||||
}
|
||||
}
|
||||
func test() {
|
||||
links := [][]string{
|
||||
|
|
@ -80,6 +84,7 @@ func test() {
|
|||
[]string{"https://lemmy.world/u/dude", "/lemmy.local/u/dude@lemmy.world", "/u/dude@lemmy.world"},
|
||||
[]string{"https://lemmy.world/u/dude@lemmy.world", "/lemmy.local/u/dude@lemmy.world", "/u/dude@lemmy.world"},
|
||||
[]string{"https://lemmy.world/post/123", "/lemmy.local/post/123@lemmy.world", "/post/123@lemmy.world"},
|
||||
[]string{"https://lemmy.world/post/123#123", "https://lemmy.world/post/123#123", "https://lemmy.world/post/123#123"},
|
||||
[]string{"/post/123", "/lemmy.local/post/123", "/post/123"},
|
||||
[]string{"/comment/123", "/lemmy.local/comment/123", "/comment/123"},
|
||||
[]string{"https://lemmy.local/comment/123", "/lemmy.local/comment/123", "/comment/123"},
|
||||
|
|
|
|||
17
public/noscript.css
Normal file
17
public/noscript.css
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
.scripting,
|
||||
.expando-button,
|
||||
.minimize,
|
||||
#showimages,
|
||||
#lmc,
|
||||
.hidechildren {
|
||||
display: none !important;
|
||||
}
|
||||
.post .expando .image img {
|
||||
visibility: visible;
|
||||
}
|
||||
div.pager {
|
||||
display: block;
|
||||
}
|
||||
.savecomment input[type=file] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
@ -219,6 +219,27 @@ summary {
|
|||
font-size: 10px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.preview h3 {
|
||||
background-color: #f0f3fc;
|
||||
border: 0px solid #e6e6e6;
|
||||
border-bottom-width: 1px;
|
||||
color: black;
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.dark .preview h3 {
|
||||
background-color: #333;
|
||||
border-color: #333;
|
||||
color: #ccc;
|
||||
}
|
||||
.preview .comment {
|
||||
margin-top: 5px;
|
||||
padding: 0px;
|
||||
}
|
||||
.preview .comment .content {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.meta a, .activity .meta a {
|
||||
color: #369;
|
||||
text-decoration: none;
|
||||
|
|
@ -262,6 +283,7 @@ summary {
|
|||
}
|
||||
form.savecomment {
|
||||
margin: 0px 0px 10px 0px;
|
||||
width: 500px;
|
||||
}
|
||||
.comment > .children > form.savecomment {
|
||||
margin: 0px 0px 10px 20px;
|
||||
|
|
@ -270,9 +292,34 @@ form.savecomment {
|
|||
margin: 5px 0px 10px 15px;
|
||||
}
|
||||
.savecomment textarea {
|
||||
width: 500px;
|
||||
margin: 5px 0px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.savecomment .upload label div {
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 32px;
|
||||
position: relative;
|
||||
background-color: #999;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.savecomment .upload input {
|
||||
display: none;
|
||||
}
|
||||
.savecomment .right {
|
||||
float:right;
|
||||
}
|
||||
.savecomment .right a {
|
||||
line-height: 28px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.comment .meta a.minimize {
|
||||
color: #369;
|
||||
font-size: 10px;
|
||||
|
|
@ -956,11 +1003,11 @@ nav .right a.mailbox {
|
|||
top: 4px;
|
||||
color: gray;
|
||||
}
|
||||
nav .right a, .right input[type=submit] {
|
||||
nav .right a, nav .right input[type=submit] {
|
||||
color: #369;
|
||||
text-decoration: none;
|
||||
}
|
||||
.dark nav .right a, .dark .right input[type=submit]{
|
||||
.dark nav .right a, .dark nav .right input[type=submit]{
|
||||
color: #dadada;
|
||||
}
|
||||
nav .right form, .comment form, form.link-btn {
|
||||
|
|
@ -1057,9 +1104,13 @@ form.create input[type=file], form.create select {
|
|||
font-size: 13px;
|
||||
margin: 10px;
|
||||
}
|
||||
.preferences div:last-child label {
|
||||
text-align: left;
|
||||
font-size: 10px;
|
||||
}
|
||||
.preferences label{
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
width: 150px;
|
||||
margin-right: 5px;
|
||||
text-align: right;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ function request(url, params, callback, errorcallback = function(){}) {
|
|||
var method = "GET"
|
||||
if (params) method = "POST"
|
||||
xmlHttp.open(method, url, true);
|
||||
if (method = "POST")
|
||||
xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xmlHttp.send(params);
|
||||
}
|
||||
function postClick(e) {
|
||||
|
|
@ -34,25 +32,31 @@ function postClick(e) {
|
|||
}
|
||||
}
|
||||
}
|
||||
function uptil (el, f) {
|
||||
if (el) return f(el) ? el : uptil(el.parentNode, f)
|
||||
}
|
||||
function commentClick(e) {
|
||||
e = e || window.event;
|
||||
var targ = e.currentTarget || e.srcElement || e;
|
||||
if (targ.nodeType == 3) targ = targ.parentNode;
|
||||
if (e.target.name=="submit") {
|
||||
e.preventDefault()
|
||||
var form = e.target.parentNode
|
||||
var form = uptil(e.target, function(el){ return el.tagName == "FORM" })
|
||||
if (form) {
|
||||
data = new FormData(form)
|
||||
data.set(e.target.name, e.target.value)
|
||||
data.set("xhr", 1)
|
||||
if (("c"+data.get("commentid")) == targ.id) {
|
||||
|
||||
targ.action = form.action
|
||||
if (e.target.value == "preview") {
|
||||
targ = form
|
||||
}
|
||||
console.log("ok")
|
||||
} 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"
|
||||
e.target.disabled = "disabled"
|
||||
request(targ.target || "", params,
|
||||
request(targ.action || "", data,
|
||||
function(res){
|
||||
targ.outerHTML = res
|
||||
setup()
|
||||
|
|
@ -217,11 +221,10 @@ function formSubmit(e) {
|
|||
var targ = e.currentTarget || e.srcElement || e;
|
||||
e.preventDefault()
|
||||
var data = new FormData(targ)
|
||||
params = new URLSearchParams(data).toString()
|
||||
params += "&" + e.submitter.name + "=" + e.submitter.value
|
||||
params += "&xhr=1"
|
||||
data.set(e.submitter.name, e.submitter.value)
|
||||
data.set("xhr", "1")
|
||||
e.submitter.disabled = "disabled"
|
||||
request(targ.target, params,
|
||||
request(targ.target, data,
|
||||
function(res){
|
||||
if (data.get("op") == "read_post") {
|
||||
document.getElementById("p"+data.get("postid")).remove()
|
||||
|
|
@ -245,19 +248,25 @@ function toggleMyCommunities(e) {
|
|||
return false
|
||||
}
|
||||
mycommunities.className = "open"
|
||||
mycommunities.innerHTML = "<div>loading</div>"
|
||||
request(e.target.href + "&xhr=1", "", function(res) {
|
||||
mycommunities.innerHTML = '<div><a href="'+e.target.href+'">view all »</a>'
|
||||
mycommunities.innerHTML += res
|
||||
}, function() {
|
||||
mycommunities.className = ""
|
||||
})
|
||||
if (mycommunities.innerHTML == "") {
|
||||
mycommunities.innerHTML = "<div>loading</div>"
|
||||
request(e.target.href + "&xhr=1", "", function(res) {
|
||||
mycommunities.innerHTML = '<div><a href="'+e.target.href+'">view all »</a>'
|
||||
mycommunities.innerHTML += res
|
||||
}, function() {
|
||||
mycommunities.className = ""
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function openSettings(e) {
|
||||
e.preventDefault()
|
||||
var settings = document.getElementById("settingspopup")
|
||||
if (settings.className == "open") {
|
||||
settings.className = ""
|
||||
return false
|
||||
}
|
||||
settings.className = "open"
|
||||
request(e.target.href + "?xhr=1", "", function(res) {
|
||||
settings.innerHTML = res
|
||||
|
|
@ -287,8 +296,7 @@ function saveSettings(e) {
|
|||
var targ = e.currentTarget || e.srcElement || e;
|
||||
var data = new FormData(targ)
|
||||
e.preventDefault()
|
||||
var params = new URLSearchParams(data).toString()
|
||||
request(targ.target, params, function(res) {
|
||||
request(targ.target, data, function(res) {
|
||||
["endlessScrolling", "autoLoad"].map(function(x) {
|
||||
localStorage.setItem(x, data.get(x)=="on")
|
||||
})
|
||||
|
|
@ -343,6 +351,16 @@ function toggleImages(open) {
|
|||
}
|
||||
}
|
||||
|
||||
function insertImg(e) {
|
||||
e = e || window.event;
|
||||
var form = uptil(e.target, function(el){ return el.tagName == "FORM" })
|
||||
form.querySelector("input[value=preview]").click()
|
||||
var inputs = form.getElementsByTagName("input")
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
inputs[i].disabled = "disabled"
|
||||
}
|
||||
}
|
||||
|
||||
function setup() {
|
||||
if (showimages = document.getElementById("se")) {
|
||||
showimages.addEventListener("click", showImages)
|
||||
|
|
@ -363,6 +381,10 @@ function setup() {
|
|||
}
|
||||
lmc.addEventListener("click", loadMoreComments)
|
||||
}
|
||||
var imgUpload = document.getElementsByClassName("imgupload")
|
||||
for (var i = 0; i < imgUpload.length; i++) {
|
||||
imgUpload[i].addEventListener("change", insertImg)
|
||||
}
|
||||
var posts = document.getElementsByClassName("post")
|
||||
for (var i = 0; i < posts.length; i++) {
|
||||
posts[i].addEventListener("click", postClick)
|
||||
|
|
|
|||
33
public/ws.js
Normal file
33
public/ws.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
var ok = false
|
||||
var t = 800
|
||||
var ws
|
||||
var prot = location.protocol == 'https:' ? "wss://":"ws://"
|
||||
let port = ":8009"
|
||||
|
||||
function start(){
|
||||
let url = prot + document.location.hostname + port + document.location.pathname + document.location.search;
|
||||
console.log('connecting to ', url);
|
||||
ws = new WebSocket(url);
|
||||
ws.onopen = function(){
|
||||
console.log("open");
|
||||
t = 800
|
||||
}
|
||||
ws.onmessage = function(msg){
|
||||
console.log("reload:", msg.data)
|
||||
if (msg.data == "") {
|
||||
return
|
||||
}
|
||||
window.location.reload()
|
||||
}
|
||||
ws.onclose = function(){
|
||||
console.log("close");
|
||||
setTimeout(function(){
|
||||
//start()
|
||||
if (t < 10 * 1000) t += 200
|
||||
}, t);
|
||||
};
|
||||
}
|
||||
console.log("ws");
|
||||
if (typeof WebSocket != 'undefined') {
|
||||
start()
|
||||
}
|
||||
147
routes.go
147
routes.go
|
|
@ -133,6 +133,8 @@ var funcMap = template.FuncMap{
|
|||
var buf bytes.Buffer
|
||||
re := regexp.MustCompile(`\s---\s`)
|
||||
body = re.ReplaceAllString(body, "\n***\n")
|
||||
// community bangs
|
||||
body = RegReplace(body, `([^\[])!([a-zA-Z0-9_]+)@([a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)+)`, `$1[!$2@$3](/c/$2@$3)`)
|
||||
if err := md.Convert([]byte(body), &buf); err != nil {
|
||||
fmt.Println(err)
|
||||
return template.HTML(body)
|
||||
|
|
@ -150,7 +152,7 @@ var funcMap = template.FuncMap{
|
|||
return body
|
||||
}
|
||||
text := html2text.HTML2TextWithOptions(buf.String(), html2text.WithLinksInnerText())
|
||||
re := regexp.MustCompile(`\<https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)\>`)
|
||||
re := regexp.MustCompile(`\<(https?:\/\/|mailto)(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)\>`)
|
||||
return re.ReplaceAllString(text, "")
|
||||
},
|
||||
"contains": strings.Contains,
|
||||
|
|
@ -164,10 +166,8 @@ var funcMap = template.FuncMap{
|
|||
|
||||
func LemmyLinkRewrite(input string, host string, lemmy_domain string) (body string) {
|
||||
body = input
|
||||
// community bangs
|
||||
body = RegReplace(body, `!([a-zA-Z0-9]+)@([a-zA-Z0-9\.\-]+)([ \n\r]+|<\/p>)`, `<a href="/c/$1@$2">!$1@$2</a> `)
|
||||
// localize community and user links
|
||||
body = RegReplace(body, `href="https:\/\/([a-zA-Z0-9\.\-]+)\/((c|u|comment|post)\/.*?)"`, `href="/$2@$1"`)
|
||||
body = RegReplace(body, `href="https:\/\/([a-zA-Z0-9\.\-]+)\/((c|u|comment|post)\/[^#\?]*?)"`, `href="/$2@$1"`)
|
||||
// remove extra instance tag
|
||||
body = RegReplace(body, `href="(https:\/)?(\/[a-zA-Z0-9\.\-]+)?\/((c|u)\/[a-zA-Z0-9]+@[a-zA-Z0-9\.\-]+)@([a-zA-Z0-9\.\-]+)"`, `href="/$3"`)
|
||||
if lemmy_domain == "" {
|
||||
|
|
@ -180,9 +180,21 @@ func LemmyLinkRewrite(input string, host string, lemmy_domain string) (body stri
|
|||
body = RegReplace(body, `href="https:\/\/`+lemmy_domain+`\/(c\/[a-zA-Z0-9]+"|(c|u|post|comment)\/(.*?)")`, `href="/$1`)
|
||||
body = RegReplace(body, `href="(.*)@`+lemmy_domain+`"`, `href="$1"`)
|
||||
}
|
||||
// remove redundant instance tag
|
||||
re := regexp.MustCompile(`href="\/([a-zA-Z0-9\.\-]+)\/(c|u|post|comment)\/(.*?)@(.*?)"`)
|
||||
|
||||
re := regexp.MustCompile(`href="\/?([a-zA-Z0-9\.\-]*)\/(c|u|post|comment)\/(.*?)@(.*?)"`)
|
||||
// assume "old." subdomain is mlmym and remove
|
||||
matches := re.FindAllStringSubmatch(body, -1)
|
||||
for _, match := range matches {
|
||||
if match[4][0:4] == "old." {
|
||||
s := 1
|
||||
if match[1] == "" {
|
||||
s += 1
|
||||
}
|
||||
body = strings.Replace(body, match[0], `href="/`+strings.Join(match[s:4], "/")+"@"+match[4][4:]+`"`, -1)
|
||||
}
|
||||
}
|
||||
// remove redundant instance tag
|
||||
matches = re.FindAllStringSubmatch(body, -1)
|
||||
for _, match := range matches {
|
||||
if match[1] == match[4] {
|
||||
body = strings.Replace(body, match[0], `href="/`+strings.Join(match[1:4], "/")+`"`, -1)
|
||||
|
|
@ -196,11 +208,23 @@ func RegReplace(input string, match string, replace string) string {
|
|||
return re.ReplaceAllString(input, replace)
|
||||
}
|
||||
|
||||
func getenv(key, fallback string) string {
|
||||
value := os.Getenv(key)
|
||||
if len(value) == 0 {
|
||||
return fallback
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func Initialize(Host string, r *http.Request) (State, error) {
|
||||
state := State{
|
||||
Host: Host,
|
||||
Page: 1,
|
||||
Status: http.StatusOK,
|
||||
Host: Host,
|
||||
Page: 1,
|
||||
Status: http.StatusOK,
|
||||
Version: version,
|
||||
}
|
||||
if watch != nil {
|
||||
state.Watch = *watch
|
||||
}
|
||||
lemmyDomain := os.Getenv("LEMMY_DOMAIN")
|
||||
if lemmyDomain != "" {
|
||||
|
|
@ -236,18 +260,27 @@ func Initialize(Host string, r *http.Request) (State, error) {
|
|||
state.Listing = getCookie(r, "DefaultListingType")
|
||||
state.Sort = getCookie(r, "DefaultSortType")
|
||||
state.CommentSort = getCookie(r, "DefaultCommentSortType")
|
||||
state.Dark = getCookie(r, "Dark") != ""
|
||||
if dark := getCookie(r, "Dark"); dark != "" {
|
||||
state.Dark = dark != "0"
|
||||
} else {
|
||||
state.Dark = os.Getenv("DARK") != ""
|
||||
}
|
||||
state.ShowNSFW = getCookie(r, "ShowNSFW") != ""
|
||||
state.HideInstanceNames = getCookie(r, "HideInstanceNames") != ""
|
||||
if hide := getCookie(r, "HideThumbnails"); hide != "" {
|
||||
state.HideThumbnails = hide != "0"
|
||||
} else {
|
||||
state.HideThumbnails = os.Getenv("HIDE_THUMBNAILS") != ""
|
||||
}
|
||||
state.ParseQuery(r.URL.RawQuery)
|
||||
if state.Sort == "" {
|
||||
state.Sort = "Hot"
|
||||
state.Sort = getenv("SORT", "Hot")
|
||||
}
|
||||
if state.CommentSort == "" {
|
||||
state.CommentSort = "Hot"
|
||||
state.CommentSort = getenv("COMMENT_SORT", "Hot")
|
||||
}
|
||||
if state.Listing == "" || state.Session == nil && state.Listing == "Subscribed" {
|
||||
state.Listing = "All"
|
||||
state.Listing = getenv("LISTING", "All")
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
|
@ -491,6 +524,9 @@ func GetPost(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
state.Op = "edit_post"
|
||||
state.GetSite()
|
||||
}
|
||||
if len(m["content"]) > 0 {
|
||||
state.Content = m["content"][0]
|
||||
}
|
||||
postid, _ := strconv.Atoi(ps.ByName("postid"))
|
||||
state.GetPost(postid)
|
||||
state.GetComments()
|
||||
|
|
@ -535,6 +571,9 @@ func GetComment(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
if len(m["edit"]) > 0 {
|
||||
state.Op = "edit"
|
||||
}
|
||||
if r.Method == "POST" && len(m["content"]) > 0 {
|
||||
state.Content = m["content"][0]
|
||||
}
|
||||
if len(m["source"]) > 0 {
|
||||
state.Op = "source"
|
||||
}
|
||||
|
|
@ -544,6 +583,10 @@ func GetComment(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
}
|
||||
commentid, _ := strconv.Atoi(ps.ByName("commentid"))
|
||||
state.GetComment(commentid)
|
||||
if state.XHR && len(m["content"]) > 0 {
|
||||
Render(w, "create_comment.html", state)
|
||||
return
|
||||
}
|
||||
state.GetPost(state.PostID)
|
||||
Render(w, "index.html", state)
|
||||
}
|
||||
|
|
@ -661,6 +704,7 @@ func Settings(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
Render(w, "index.html", state)
|
||||
return
|
||||
}
|
||||
state.GetSite()
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
for _, name := range []string{"DefaultSortType", "DefaultListingType", "DefaultCommentSortType"} {
|
||||
|
|
@ -671,8 +715,7 @@ func Settings(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
setCookie(w, "", "Dark", "1")
|
||||
state.Dark = true
|
||||
} else {
|
||||
deleteCookie(w, state.Host, "Dark")
|
||||
deleteCookie(w, "", "Dark")
|
||||
setCookie(w, "", "Dark", "0")
|
||||
state.Dark = false
|
||||
}
|
||||
if r.FormValue("shownsfw") != "" {
|
||||
|
|
@ -690,6 +733,13 @@ func Settings(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
deleteCookie(w, "", "HideInstanceNames")
|
||||
state.HideInstanceNames = false
|
||||
}
|
||||
if r.FormValue("hideThumbnails") != "" {
|
||||
setCookie(w, "", "HideThumbnails", "1")
|
||||
state.HideInstanceNames = true
|
||||
} else {
|
||||
setCookie(w, "", "HideThumbnails", "0")
|
||||
state.HideInstanceNames = false
|
||||
}
|
||||
state.Listing = r.FormValue("DefaultListingType")
|
||||
state.Sort = r.FormValue("DefaultSortType")
|
||||
state.CommentSort = r.FormValue("DefaultCommentSortType")
|
||||
|
|
@ -1185,9 +1235,20 @@ func UserOp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
parentid, _ := strconv.Atoi(r.FormValue("parentid"))
|
||||
state.GetComment(parentid)
|
||||
}
|
||||
content := r.FormValue("content")
|
||||
file, handler, err := r.FormFile("file")
|
||||
if err == nil {
|
||||
pres, err := state.UploadImage(file, handler)
|
||||
if err != nil {
|
||||
state.Error = err
|
||||
Render(w, "index.html", state)
|
||||
return
|
||||
}
|
||||
content += ("")
|
||||
}
|
||||
if r.FormValue("submit") == "save" {
|
||||
createComment := types.CreateComment{
|
||||
Content: r.FormValue("content"),
|
||||
Content: content,
|
||||
PostID: state.PostID,
|
||||
}
|
||||
if state.CommentID > 0 {
|
||||
|
|
@ -1209,6 +1270,22 @@ func UserOp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else if r.FormValue("submit") == "preview" {
|
||||
q := r.URL.Query()
|
||||
q.Set("content", content)
|
||||
q.Set("reply", "")
|
||||
if r.FormValue("xhr") != "" {
|
||||
q.Set("xhr", "1")
|
||||
}
|
||||
r.URL.RawQuery = q.Encode()
|
||||
if ps.ByName("postid") != "" {
|
||||
GetPost(w, r, ps)
|
||||
return
|
||||
}
|
||||
if ps.ByName("commentid") != "" {
|
||||
GetComment(w, r, ps)
|
||||
return
|
||||
}
|
||||
} else if r.FormValue("xhr") != "" {
|
||||
w.Write([]byte{})
|
||||
return
|
||||
|
|
@ -1218,10 +1295,23 @@ func UserOp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
}
|
||||
case "edit_comment":
|
||||
commentid, _ := strconv.Atoi(r.FormValue("commentid"))
|
||||
q := r.URL.Query()
|
||||
content := r.FormValue("content")
|
||||
file, handler, err := r.FormFile("file")
|
||||
if err == nil {
|
||||
pres, err := state.UploadImage(file, handler)
|
||||
if err != nil {
|
||||
state.Error = err
|
||||
Render(w, "index.html", state)
|
||||
return
|
||||
}
|
||||
content += ("")
|
||||
}
|
||||
|
||||
if r.FormValue("submit") == "save" {
|
||||
resp, err := state.Client.EditComment(context.Background(), types.EditComment{
|
||||
CommentID: commentid,
|
||||
Content: types.NewOptional(r.FormValue("content")),
|
||||
Content: types.NewOptional(content),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
|
@ -1230,6 +1320,29 @@ func UserOp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||
r.URL.Fragment = "c" + commentid
|
||||
r.URL.RawQuery = ""
|
||||
}
|
||||
} else if r.FormValue("submit") == "preview" {
|
||||
q.Set("content", content)
|
||||
q.Set("edit", "")
|
||||
if r.FormValue("xhr") != "" {
|
||||
q.Set("xhr", "1")
|
||||
}
|
||||
r.URL.RawQuery = q.Encode()
|
||||
if ps.ByName("commentid") != "" {
|
||||
GetComment(w, r, ps)
|
||||
return
|
||||
}
|
||||
} else if r.FormValue("submit") == "cancel" {
|
||||
if ps.ByName("commentid") != "" {
|
||||
if r.FormValue("xhr") != "" {
|
||||
q.Set("xhr", "1")
|
||||
}
|
||||
r.URL.RawQuery = q.Encode()
|
||||
GetComment(w, r, ps)
|
||||
return
|
||||
}
|
||||
} else if r.FormValue("xhr") != "" {
|
||||
w.Write([]byte{})
|
||||
return
|
||||
}
|
||||
if r.FormValue("xhr") != "" {
|
||||
state.XHR = true
|
||||
|
|
|
|||
36
state.go
36
state.go
|
|
@ -59,11 +59,14 @@ type Post struct {
|
|||
}
|
||||
|
||||
type Session struct {
|
||||
UserName string
|
||||
UserID int
|
||||
UserName string
|
||||
UserID int
|
||||
Communities []types.CommunityView
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Watch bool
|
||||
Version string
|
||||
Client *lemmy.Client
|
||||
HTTPClient *http.Client
|
||||
Session *Session
|
||||
|
|
@ -95,11 +98,13 @@ type State struct {
|
|||
Op string
|
||||
Site *types.GetSiteResponse
|
||||
Query string
|
||||
Content string
|
||||
SearchType string
|
||||
Captcha *types.CaptchaResponse
|
||||
Dark bool
|
||||
ShowNSFW bool
|
||||
HideInstanceNames bool
|
||||
HideThumbnails bool
|
||||
}
|
||||
|
||||
func (s State) Unknown() string {
|
||||
|
|
@ -266,6 +271,18 @@ func (state *State) GetSite() {
|
|||
return
|
||||
}
|
||||
state.Site = resp
|
||||
if !state.Site.MyUser.IsValid() {
|
||||
return
|
||||
}
|
||||
for _, c := range state.Site.MyUser.MustValue().Follows {
|
||||
state.Session.Communities = append(state.Session.Communities, types.CommunityView{
|
||||
Community: c.Community,
|
||||
Subscribed: "Subscribed",
|
||||
})
|
||||
}
|
||||
sort.Slice(state.Session.Communities, func(a, b int) bool {
|
||||
return state.Session.Communities[a].Community.Name < state.Session.Communities[b].Community.Name
|
||||
})
|
||||
}
|
||||
|
||||
func (state *State) GetComment(commentid int) {
|
||||
|
|
@ -299,6 +316,9 @@ func (state *State) GetComment(commentid int) {
|
|||
state.Comments = append(state.Comments, comment)
|
||||
}
|
||||
}
|
||||
if len(state.Comments) == 0 {
|
||||
return
|
||||
}
|
||||
ctx, err := state.GetContext(state.Context, state.Comments[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
|
@ -531,16 +551,10 @@ func (state *State) Search(searchtype string) {
|
|||
if state.Page > 1 {
|
||||
return
|
||||
}
|
||||
state.GetSite()
|
||||
for _, c := range state.Site.MyUser.MustValue().Follows {
|
||||
state.Communities = append(state.Communities, types.CommunityView{
|
||||
Community: c.Community,
|
||||
Subscribed: "Subscribed",
|
||||
})
|
||||
if state.Site == nil {
|
||||
state.GetSite()
|
||||
}
|
||||
sort.Slice(state.Communities, func(a, b int) bool {
|
||||
return state.Communities[a].Community.Name < state.Communities[b].Community.Name
|
||||
})
|
||||
state.Communities = state.Session.Communities
|
||||
return
|
||||
}
|
||||
resp, err := state.Client.Communities(context.Background(), types.ListCommunities{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="comment{{if or (lt .P.Counts.Score -5) .P.Comment.Deleted }} hidden{{end}}" id="c{{.P.Comment.ID}}">
|
||||
<div class="comment{{if or (lt .P.Counts.Score -5) .P.Comment.Deleted .P.Comment.Removed }} hidden{{end}}" id="c{{.P.Comment.ID}}">
|
||||
{{ if .State.Session }}
|
||||
<div class="score">
|
||||
<form class="link-btn{{ if eq .P.MyVote.String "1"}} like{{ else if eq .P.MyVote.String "-1"}} dislike{{end}}" method="POST">
|
||||
|
|
@ -15,11 +15,11 @@
|
|||
{{ end }}
|
||||
<div class="meta">
|
||||
<a class="minimize" href="" for="c{{.P.Comment.ID}}">
|
||||
{{if or (lt .P.Counts.Score -5) .P.Comment.Deleted }}
|
||||
{{- if or (lt .P.Counts.Score -5) .P.Comment.Deleted -}}
|
||||
[+]
|
||||
{{ else }}
|
||||
{{- else -}}
|
||||
[-]
|
||||
{{ end }}
|
||||
{{- end -}}
|
||||
</a>
|
||||
<a {{ if .P.Comment.Distinguished}}class="{{if .P.Creator.Admin}}admin {{end}}distinguished"{{ else if .Submitter }}class="submitter"{{end}} href="/{{.State.Host}}/u/{{fullname .P.Creator}}">
|
||||
{{- if .State.HideInstanceNames -}}
|
||||
|
|
@ -33,32 +33,26 @@
|
|||
* (last edited <span title="{{.P.Comment.Updated.Time}}">{{ humanize .P.Comment.Updated.Time }}</span>)
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="content">
|
||||
{{ 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 name="submit" type="submit" value="save">
|
||||
<input name="submit" type="submit" value="cancel">
|
||||
</form>
|
||||
{{ template "create_comment.html" .State }}
|
||||
{{ else }}
|
||||
<div class="content">
|
||||
{{if .P.Comment.Deleted}}
|
||||
[removed]
|
||||
{{else}}
|
||||
{{if .P.Comment.Deleted}}
|
||||
[deleted]
|
||||
{{else if .P.Comment.Removed }}
|
||||
[removed by mod]
|
||||
{{else}}
|
||||
<div {{ if and .Selected (not .State.XHR) (ne .State.Op "reply")}}class="highlight" {{end}}>
|
||||
{{ markdown .State.Host .P.Comment.Content }}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{ if eq .Op "source" }}
|
||||
<div><textarea>{{.P.Comment.Content}}</textarea></div>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
<ul class="buttons">
|
||||
<li><a href="/{{.State.Host}}/comment/{{.P.Comment.ID}}">permalink</a></li>
|
||||
<li><a href="{{.P.Comment.ApID}}">fedilink</a></li>
|
||||
{{ if ne .Op "source"}}
|
||||
<li><a class="source" for="c{{.P.Comment.ID}}" href="/{{.State.Host}}/comment/{{.P.Comment.ID}}?source">source</a></li>
|
||||
{{ else }}
|
||||
|
|
@ -93,7 +87,7 @@
|
|||
</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ if and .ParentID .State.CommentID }}
|
||||
{{ if and .ParentID .State.CommentID (not .State.XHR) }}
|
||||
<li>
|
||||
<a href="/{{.State.Host}}/comment/{{.ParentID}}">parent</a>
|
||||
</li>
|
||||
|
|
@ -110,15 +104,7 @@
|
|||
</div>
|
||||
<div class="children">
|
||||
{{ if and (eq .State.Op "reply") (eq .State.CommentID .P.Comment.ID)}}
|
||||
<form class="savecomment" method="POST">
|
||||
<div>
|
||||
<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" name="submit" value="save">
|
||||
<input type="submit" name="submit" value="cancel">
|
||||
</form>
|
||||
{{ template "create_comment.html" .State }}
|
||||
{{ end}}
|
||||
{{ range $ci, $child := .C }}{{ template "comment.html" $child }}{{end}}
|
||||
{{ if and (ne .P.Counts.ChildCount .ChildCount) (not .State.Activities) (not .State.Query) }}
|
||||
|
|
@ -128,4 +114,4 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
45
templates/create_comment.html
Normal file
45
templates/create_comment.html
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<form class="savecomment" method="POST" enctype="multipart/form-data"
|
||||
{{- if .CommentID }} action="/{{.Host}}/comment/{{.CommentID}}"
|
||||
{{- else }} action="/{{.Host}}/post/{{.PostID}}"
|
||||
{{- end -}}
|
||||
>
|
||||
<div class="upload">
|
||||
<label title="upload photo"><div>📷</div>
|
||||
<input class="imgupload" type="file" name="file" accept="image/*">
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="content">
|
||||
{{- if .Content }}
|
||||
{{- .Content -}}
|
||||
{{ else if and (eq .Op "edit") .Comments }}
|
||||
{{- (index .Comments 0).P.Comment.Content -}}
|
||||
{{ end -}}
|
||||
</textarea>
|
||||
</div>
|
||||
{{ if eq .Op "edit" }}
|
||||
<input type="hidden" name="op" value="edit_comment">
|
||||
<input type="hidden" name="commentid" value="{{.CommentID}}">
|
||||
{{ else }}
|
||||
<input type="hidden" name="op" value="create_comment">
|
||||
{{ end }}
|
||||
<input type="hidden" name="parentid" value="{{.CommentID}}">
|
||||
<input type="submit" name="submit" value="save">
|
||||
{{ if or .Op .Content }}
|
||||
<input type="submit" name="submit" value="cancel">
|
||||
{{ end }}
|
||||
<div class="right">
|
||||
<a href="https://join-lemmy.org/docs/users/02-media.html" target="_blank">formatting help</a>
|
||||
<input name="submit" type="submit" value="preview">
|
||||
</div>
|
||||
{{ if .Content }}
|
||||
<div class="preview">
|
||||
<div class="comment">
|
||||
<h3>Preview</h3>
|
||||
<div class="content">
|
||||
{{ markdown .Host .Content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</form>
|
||||
|
|
@ -2,26 +2,12 @@
|
|||
<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=27">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v={{ .Version }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body {{ if .Dark }}class="dark"{{end}}>
|
||||
<noscript>
|
||||
<style>
|
||||
.expando-button,
|
||||
.minimize,
|
||||
#loadmore,
|
||||
#showimages,
|
||||
.hidechildren {
|
||||
display: none;
|
||||
}
|
||||
div.pager {
|
||||
display: block;
|
||||
}
|
||||
.post .expando .image img {
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/_/static/noscript.css?v={{ .Version }}">
|
||||
</noscript>
|
||||
|
||||
{{ template "nav.html" . -}}
|
||||
|
|
@ -59,6 +45,6 @@
|
|||
{{ template "sidebar.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
<script src="/_/static/utils.js?v=21"></script>
|
||||
<script src="/_/static/utils.js?v={{ .Version }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<head>
|
||||
<title>{{ host .Host }}: sign up or log in</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={{ .Version }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body {{ if .Dark }}class="dark"{{end}}>
|
||||
|
|
|
|||
|
|
@ -3,23 +3,11 @@
|
|||
<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=27">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v={{ .Version }}">
|
||||
</head>
|
||||
<body{{ if .Dark }} class="dark"{{end}}>
|
||||
<noscript>
|
||||
<style>
|
||||
.scripting,
|
||||
.expando-button,
|
||||
.minimize,
|
||||
#showimages,
|
||||
#lmc,
|
||||
.hidechildren {
|
||||
display: none !important;
|
||||
}
|
||||
.post .expando .image img {
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/_/static/noscript.css?v={{ .Version }}">
|
||||
</noscript>
|
||||
|
||||
{{ template "nav.html" . -}}
|
||||
|
|
@ -99,13 +87,9 @@
|
|||
</div>
|
||||
</div>
|
||||
{{ if and .Session (ne .Op "edit_post") }}
|
||||
<form class="savecomment" method="POST">
|
||||
<div>
|
||||
<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" name="submit" value="save"{{ if (index .Posts 0).Post.Deleted }} disabled {{end}}>
|
||||
</form>
|
||||
<div class="create_comment">
|
||||
{{ template "create_comment.html" .}}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end}}
|
||||
|
|
@ -140,7 +124,10 @@
|
|||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<script src="/_/static/utils.js?v=21"></script>
|
||||
<script src="/_/static/utils.js?v={{ .Version }}"></script>
|
||||
{{ if .Watch }}
|
||||
<script src="/_/static/ws.js"></script>
|
||||
{{ end }}
|
||||
{{ template "sidebar.html" . }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{{ $state := . }}
|
||||
<nav>
|
||||
<div class="communities">
|
||||
{{ if .Session }}
|
||||
|
|
@ -14,7 +15,14 @@
|
|||
{{ end }}
|
||||
<a href="/{{$host}}/search?searchtype=Communities&sort=TopMonth" class="more">more »</a>
|
||||
</div>
|
||||
<div id="mycommunities"></div>
|
||||
<div id="mycommunities">
|
||||
{{- if and .Session .Session.Communities }}
|
||||
<a href="/{{.Host}}/search?searchtype=Communities&listingType=Subscribed&sort=TopMonth&page=0">view all »</a>
|
||||
{{ range .Session.Communities }}
|
||||
<a href="/{{ $state.Host}}/{{ if .Community.Local }}c/{{.Community.Name}}{{else}}{{ localize .Community.ActorID }}{{end}}">{{fullcname .Community }}</a>
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
</div>
|
||||
<div class="right">
|
||||
{{ if .Session }}
|
||||
<a href="/{{.Host}}/u/{{ .Session.UserName}}">{{ .Session.UserName }}</a>
|
||||
|
|
|
|||
|
|
@ -23,17 +23,19 @@
|
|||
{{ end }}
|
||||
{{ if and (ne .State.Op "vote_post") (ne .State.Op "save_post") }}
|
||||
</div>
|
||||
{{ if not .State.HideThumbnails }}
|
||||
<div class="thumb">
|
||||
<a class="url" href="{{ if .Post.URL.IsValid }}{{ .Post.URL }}{{ else }}/{{ .State.Host }}/post/{{ .Post.ID }}{{ end }}">
|
||||
<div {{ if and .Post.NSFW (not (and .State.Community .State.Community.CommunityView.Community.NSFW))}}class="img-blur"{{end}} style="background-image: url({{thumbnail .Post}})"></div>
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="entry">
|
||||
<div class="title">
|
||||
<a class="url" href="{{ if .Post.URL.IsValid }}{{ .Post.URL }}{{ else }}/{{ .State.Host }}/post/{{ .Post.ID }}{{ end }}">{{ rmmarkdown .Post.Name }}</a>
|
||||
({{ domain . }})
|
||||
</div>
|
||||
<div class="expando-button {{ if and (not (and .Post.Body.IsValid .Post.Body.String )) (not (isImage .Post.URL.String)) }}hidden{{else if eq .Rank 0}}open{{ end }}"></div>
|
||||
<div class="expando-button{{ if and (not (and .Post.Body.IsValid .Post.Body.String )) (not (isImage .Post.URL.String)) }} hidden{{else if eq .Rank 0}} open{{ end }}"></div>
|
||||
<div class="meta">
|
||||
submitted
|
||||
<span title="{{.Post.Published.Time}}">{{ humanize .Post.Published.Time -}}</span>
|
||||
|
|
@ -60,6 +62,7 @@
|
|||
<div class="buttons">
|
||||
{{ if .Post.NSFW }}<span class="nsfw">NSFW</span>{{end}}
|
||||
<a href="/{{ .State.Host }}/post/{{ .Post.ID }}">{{ .Counts.Comments }} comments</a>
|
||||
<a href="{{ .Post.ApID}}">fedilink</a>
|
||||
{{ if and .State.Session (eq .State.Session.UserID .Post.CreatorID) }}
|
||||
{{ if not .Post.Deleted }}<a href="/{{ .State.Host }}/post/{{ .Post.ID }}?edit">edit</a>{{end}}
|
||||
<form class="link-btn" method="POST">
|
||||
|
|
@ -106,7 +109,7 @@
|
|||
</div>
|
||||
<div></div>
|
||||
<div class="clearleft"></div>
|
||||
<div class="expando {{ if eq .Rank 0 }}open{{ end}}">
|
||||
<div class="expando{{ if eq .Rank 0 }} open{{ end}}">
|
||||
{{ if (and .Post.Body.IsValid (ne .Post.Body.String "")) }}
|
||||
<div class="md">{{ markdown .State.Host .Post.Body.String }}</div>
|
||||
{{ end }}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,12 @@
|
|||
<head>
|
||||
<title>{{ host .Host }}: preferences</title>
|
||||
<link rel="shortcut icon" href="/{{.Host}}/icon.jpg">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v=15">
|
||||
<link rel="stylesheet" href="/_/static/style.css?v={{ .Version }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body {{ if .Dark}}class="dark"{{end}}>
|
||||
<noscript>
|
||||
<style>
|
||||
.scripting {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/_/static/noscript.css?v={{ .Version }}">
|
||||
</noscript>
|
||||
<nav>
|
||||
<div class="communities">
|
||||
|
|
@ -129,13 +125,19 @@
|
|||
<input type="checkbox" name="hideInstanceNames" {{ if .HideInstanceNames }}checked{{end}}>
|
||||
</div>
|
||||
<div>
|
||||
<label></label>
|
||||
<label>
|
||||
hide thumbnails
|
||||
</label>
|
||||
<input type="checkbox" name="hideThumbnails" {{ if .HideThumbnails }}checked{{end}}>
|
||||
</div>
|
||||
<div>
|
||||
<label>lemmy: {{ .Site.Version }}<br><a href="https://github.com/rystaf/mlmym">mlmym</a>: {{ .Version }}</label>
|
||||
<input type="submit" value="save">
|
||||
{{ if .XHR }}<input id="closesettings" type="submit" value="close">{{ end }}
|
||||
</div>
|
||||
</form>
|
||||
{{ if not .XHR}}
|
||||
<script src="/_/static/utils.js?v=8"></script>
|
||||
<script src="/_/static/utils.js?v={{ .Version }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue