2018-11-08 06:11:42 +01:00
{{define "pad"}}<!DOCTYPE HTML>
<html>
<head>
<title>{{if .Editing}}Editing {{if .Post.Title}}{{.Post.Title}}{{else}}{{.Post.Id}}{{end}}{{else}}New Post{{end}} — {{.SiteName}}</title>
<link rel="stylesheet" type="text/css" href="/css/write.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" value="notranslate">
</head>
<body id="pad" class="light">
<div id="overlay"></div>
<textarea id="writer" placeholder="Write..." class="{{.Post.Font}}" autofocus>{{if .Post.Title}} # {{.Post.Title}}
{{end}}{{.Post.Content}}</textarea>
2020-06-11 17:45:12 +02:00
<div class="alert success hidden" id="edited-elsewhere">This post has been updated elsewhere since you last published! <a href=" #" id="erase-edit">Delete draft and reload</a>.</div>
2018-11-08 06:11:42 +01:00
<header id="tools">
<div id="clip">
2018-11-10 04:10:46 +01:00
{{if not .SingleUser}}<h1><a href="/me/c/" title="View blogs"><img class="ic-24dp" src="/img/ic_blogs_dark@2x.png" /></a></h1>{{end}}
<nav id="target" {{if .SingleUser}}style="margin-left:0"{{end}}><ul>
2018-11-08 06:11:42 +01:00
{{if .Editing}}<li>{{if .EditCollection}}<a href="{{.EditCollection.CanonicalURL}}">{{.EditCollection.Title}}</a>{{else}}<a>Draft</a>{{end}}</li>
2020-07-30 17:26:29 +02:00
{{else}}<li class="has-submenu"><a id="publish-to"><span id="target-name">Draft</span> <img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /></a>
2018-11-08 06:11:42 +01:00
<ul>
<li class="menu-heading">Publish to...</li>
2019-10-02 19:20:51 +02:00
{{if .Blogs}}{{range $ idx , $ el := .Blogs}}
<li class="target{{if eq $ idx 0}} selected{{end}}" id="blog-{{ $ el . Alias }}"><a href=" #{{ $ el . Alias }}"><i class="material-icons md-18">public</i> {{if $ el . Title }}{{ $ el . Title }}{{else}}{{ $ el . Alias }}{{end}}</a></li>
2018-11-08 06:11:42 +01:00
{{end}}{{end}}
2019-10-02 19:20:51 +02:00
<li class="target" id="blog-anonymous"><a href=" #anonymous " ><i class= " material - icons md - 18 " >description</i> <em>Draft</em></a></li>
2018-11-08 06:11:42 +01:00
<li id="user-separator" class="separator"><hr /></li>
2018-11-10 04:10:46 +01:00
{{ if .SingleUser }}
<li><a href="/"><i class="material-icons md-18">launch</i> View Blog</a></li>
<li><a href="/me/c/{{.Username}}"><i class="material-icons md-18">palette</i> Customize</a></li>
<li><a href="/me/c/{{.Username}}/stats"><i class="material-icons md-18">trending_up</i> Stats</a></li>
{{ else }}
2018-11-08 06:11:42 +01:00
<li><a href="/me/c/"><i class="material-icons md-18">library_books</i> View Blogs</a></li>
2018-11-10 04:10:46 +01:00
{{ end }}
2018-11-08 06:11:42 +01:00
<li><a href="/me/posts/"><i class="material-icons md-18">view_list</i> View Drafts</a></li>
<li><a href="/me/logout"><i class="material-icons md-18">power_settings_new</i> Log out</a></li>
</ul>
</li>{{end}}
</ul></nav>
<nav id="font-picker" class="if-room room-3 hidden" style="margin-left:-1em"><ul>
2020-07-30 17:26:29 +02:00
<li class="has-submenu"><a href=" #" id="" onclick="return false"><img class="ic-24dp" src="/img/ic_font_dark@2x.png" /> <img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /></a>
2018-11-08 06:11:42 +01:00
<ul style="text-align: center">
<li class="menu-heading">Font</li>
<li class="selected"><a class="font norm" href=" #norm " >Serif</a></li>
<li><a class="font sans" href=" #sans " >Sans-serif</a></li>
<li><a class="font wrap" href=" #wrap " >Monospace</a></li>
</ul>
</li>
</ul></nav>
<span id="wc" class="hidden if-room room-4">0 words</span>
</div>
<noscript style="margin-left: 2em;"><strong>NOTE</strong>: for now, you'll need Javascript enabled to post.</noscript>
<div id="belt">
2018-11-10 04:10:46 +01:00
{{if .Editing}}<div class="tool hidden if-room"><a href="{{if .EditCollection}}{{.EditCollection.CanonicalURL}}{{.Post.Slug}}/edit/meta{{else}}/{{if .SingleUser}}d/{{end}}{{.Post.Id}}/meta{{end}}" title="Edit post metadata" id="edit-meta"><img class="ic-24dp" src="/img/ic_info_dark@2x.png" /></a></div>{{end}}
2018-11-08 06:11:42 +01:00
<div class="tool hidden if-room room-2"><a href=" #theme " title= " Toggle theme " id= " toggle - theme " ><img class= " ic - 24 dp " src= " / img / ic_brightness_dark @ 2 x . png " /></a></div>
<div class="tool if-room room-1"><a href="{{if not .User}}/pad/posts{{else}}/me/posts/{{end}}" title="View posts" id="view-posts"><img class="ic-24dp" src="/img/ic_list_dark@2x.png" /></a></div>
<div class="tool"><a href=" #publish " title= " Publish " id= " publish " ><img class= " ic - 24 dp " src= " / img / ic_send_dark @ 2 x . png " /></a></div>
</div>
</header>
<script src="/js/h.js"></script>
2020-07-30 17:26:29 +02:00
<script type="text/javascript" src="/js/menu.js"></script>
2018-11-08 06:11:42 +01:00
<script>
function toggleTheme() {
if (document.body.classList.contains('light')) {
2019-06-25 21:33:58 +02:00
setTheme('dark');
} else {
setTheme('light');
}
H.set('padTheme', newTheme);
}
2020-08-11 15:27:50 +02:00
function setTheme(newTheme) {
2019-06-25 21:33:58 +02:00
document.body.classList.remove('light');
document.body.classList.remove('dark');
document.body.classList.add(newTheme);
var btns = Array.prototype.slice.call(document.getElementById('tools').querySelectorAll('a img'));
2020-08-11 15:27:50 +02:00
if (newTheme == 'light') {
2019-06-25 21:33:58 +02:00
// check if current theme is dark otherwise we'll get `_dark_dark@2x.png`
if (H.get('padTheme', 'auto') == 'dark'){
for (var i=0; i<btns.length; i++) {
btns[i].src = btns[i].src.replace('@2x.png', '_dark@2x.png');
}
2018-11-08 06:11:42 +01:00
}
} else {
for (var i=0; i<btns.length; i++) {
2019-06-25 21:33:58 +02:00
btns[i].src = btns[i].src.replace('_dark@2x.png', '@2x.png');
2018-11-08 06:11:42 +01:00
}
}
H.set('padTheme', newTheme);
}
2019-06-25 21:33:58 +02:00
if (H.get('padTheme', 'auto') == 'light') {
setTheme('light');
2020-08-11 15:27:50 +02:00
} else if (H.get('padTheme', 'auto') == 'dark') {
2019-06-25 21:33:58 +02:00
setTheme('dark');
} else {
const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches
2020-08-11 15:27:50 +02:00
if (isDarkMode) {
setTheme('dark');
} else {
setTheme('light');
}
2018-11-08 06:11:42 +01:00
}
2019-06-25 21:33:58 +02:00
2018-11-08 06:11:42 +01:00
var $ writer = H.getEl('writer');
var $ btnPublish = H.getEl('publish');
2020-06-11 17:45:12 +02:00
var $ btnEraseEdit = H.getEl('edited-elsewhere');
2018-11-08 06:11:42 +01:00
var $ wc = H.getEl("wc");
var updateWordCount = function() {
var words = 0;
var val = $ writer . el . value . trim ();
if (val != '') {
words = $ writer . el . value . trim ().replace(/\s+/gi, ' ').split(' ').length;
}
$ wc . el . innerText = words + " word" + (words != 1 ? "s" : "");
};
var setButtonStates = function() {
if (!canPublish) {
$ btnPublish . el . className = 'disabled';
return;
}
if ( $ writer . el . value . length === 0 || (draftDoc != 'lastDoc' && $ writer . el . value == origDoc)) {
$ btnPublish . el . className = 'disabled';
} else {
$ btnPublish . el . className = '';
}
};
{{if .Post.Id}}var draftDoc = 'draft{{.Post.Id}}';
var origDoc = '{{.Post.Content}}';{{else}}var draftDoc = 'lastDoc';{{end}}
2020-06-11 17:45:12 +02:00
var updatedStr = '{{.Post.Updated8601}}';
var updated = null;
if (updatedStr != '') {
updated = new Date(updatedStr);
}
var ok = H.load( $ writer , draftDoc, true, updated);
if (!ok) {
// Show "edited elsewhere" warning
$ btnEraseEdit . el . classList . remove ('hidden');
}
var defaultTimeSet = false;
2018-11-08 06:11:42 +01:00
updateWordCount();
var typingTimer;
var doneTypingInterval = 200;
var posts;
{{if and .Post.Id (not .Post.Slug)}}
var token = null;
var curPostIdx;
posts = JSON.parse(H.get('posts', '[]'));
for (var i=0; i<posts.length; i++) {
if (posts[i].id == "{{.Post.Id}}") {
token = posts[i].token;
break;
}
}
var canPublish = token != null;
{{else}}var canPublish = true;{{end}}
var publishing = false;
var justPublished = false;
2019-11-12 00:21:45 +01:00
var silenced = {{.Silenced}};
2018-11-08 06:11:42 +01:00
var publish = function(content, font) {
2019-11-12 00:21:45 +01:00
if (silenced === true) {
2019-11-11 16:16:44 +01:00
alert("Your account is silenced, so you can't publish or update posts.");
2019-08-28 21:37:45 +02:00
return;
}
2018-11-08 06:11:42 +01:00
{{if and (and .Post.Id (not .Post.Slug)) (not .User)}}
if (!token) {
alert("You don't have permission to update this post.");
return;
}
if ( $ btnPublish . el . className == 'disabled') {
return;
}
{{end}}
$ btnPublish . el . children [0].textContent = 'more_horiz';
publishing = true;
var xpostTarg = H.get('crosspostTarget', '[]');
var http = new XMLHttpRequest();
var post = H.getTitleStrict(content);
var params = {
body: post.content,
title: post.title,
2021-04-06 18:37:26 +02:00
font: font
};
2018-11-08 06:11:42 +01:00
{{ if .Post.Slug }}
var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}";
{{ else if .Post.Id }}
var url = "/api/posts/{{.Post.Id}}";
if (typeof token === 'undefined' || !token) {
token = "";
}
params.token = token;
{{ else }}
2021-04-06 18:37:26 +02:00
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
params.lang = lang;
2018-11-08 06:11:42 +01:00
var url = "/api/posts";
var postTarget = H.get('postTarget', 'anonymous');
if (postTarget != 'anonymous') {
url = "/api/collections/" + postTarget + "/posts";
}
params.crosspost = JSON.parse(xpostTarg);
{{ end }}
http.open("POST", url, true);
// Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/json");
http.onreadystatechange = function() {
if (http.readyState == 4) {
publishing = false;
if (http.status == 200 || http.status == 201) {
data = JSON.parse(http.responseText);
id = data.data.id;
2018-11-10 04:10:46 +01:00
nextURL = '{{if .SingleUser}}/d{{end}}/'+id;
2020-06-11 17:45:12 +02:00
localStorage.setItem('draft'+id+'-published', new Date().toISOString());
2018-11-08 06:11:42 +01:00
{{ if not .Post.Id }}
// Post created
if (postTarget != 'anonymous') {
2018-11-10 04:10:46 +01:00
nextURL = {{if not .SingleUser}}'/'+postTarget+{{end}}'/'+data.data.slug;
2018-11-08 06:11:42 +01:00
}
editToken = data.data.token;
{{ if not .User }}if (postTarget == 'anonymous') {
// Save the data
var posts = JSON.parse(H.get('posts', '[]'));
{{if .Post.Id}}var newPost = H.createPost("{{.Post.Id}}", token, content);
for (var i=0; i<posts.length; i++) {
if (posts[i].id == "{{.Post.Id}}") {
posts[i].title = newPost.title;
posts[i].summary = newPost.summary;
break;
}
}
nextURL = "/pad/posts";{{else}}posts.push(H.createPost(id, editToken, content));{{end}}
H.set('posts', JSON.stringify(posts));
}
{{ end }}
{{ end }}
justPublished = true;
if (draftDoc != 'lastDoc') {
H.remove(draftDoc);
{{if .Editing}}H.remove('draft{{.Post.Id}}font');{{end}}
} else {
H.set(draftDoc, '');
}
{{if .EditCollection}}
window.location = '{{.EditCollection.CanonicalURL}}{{.Post.Slug}}';
{{else}}
window.location = nextURL;
{{end}}
} else {
$ btnPublish . el . children [0].textContent = 'send';
alert("Failed to post. Please try again.");
}
}
}
http.send(JSON.stringify(params));
};
setButtonStates();
$ writer . on ('keyup input', function() {
setButtonStates();
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}, false);
$ writer . on ('keydown', function(e) {
clearTimeout(typingTimer);
if (e.keyCode == 13 && (e.metaKey || e.ctrlKey)) {
$ btnPublish . el . click ();
}
});
$ btnPublish . on ('click', function(e) {
e.preventDefault();
if (!publishing && $ writer . el . value ) {
var content = $ writer . el . value ;
publish(content, selectedFont);
}
});
2020-06-11 17:45:12 +02:00
H.getEl('erase-edit').on('click', function(e) {
e.preventDefault();
H.remove(draftDoc);
H.remove(draftDoc+'-published');
justPublished = true; // Block auto-save
location.reload();
});
2018-11-08 06:11:42 +01:00
H.getEl('toggle-theme').on('click', function(e) {
e.preventDefault();
var newTheme = 'light';
if (document.body.className == 'light') {
newTheme = 'dark';
}
toggleTheme();
});
var targets = document.querySelectorAll(' #target li . target a ' );
for (var i=0; i<targets.length; i++) {
targets[i].addEventListener('click', function(e) {
e.preventDefault();
var targetName = this.href.substring(this.href.indexOf(' #')+1);
H.set('postTarget', targetName);
document.querySelector(' #target li . target . selected ' ).classList.remove( ' selected ' );
this.parentElement.classList.add('selected');
var newText = this.innerText.split(' ');
newText.shift();
document.getElementById('target-name').innerText = newText.join(' ');
});
}
2019-10-02 19:20:51 +02:00
var postTarget = H.get('postTarget', '{{if .Blogs}}{{ $ blog := index .Blogs 0}}{{ $ blog . Alias }}{{else}}anonymous{{end}}');
2018-11-08 06:11:42 +01:00
if (location.hash != '') {
postTarget = location.hash.substring(1);
// TODO: pushState to /pad (or whatever the URL is) so we live on a clean URL
location.hash = '';
}
var pte = document.querySelector(' #target li . target # blog-'+postTarget+' a');
if (pte != null) {
pte.click();
} else {
postTarget = 'anonymous';
H.set('postTarget', postTarget);
}
var sansLoaded = false;
WebFontConfig = {
custom: { families: [ 'Lora:400,700:latin' ], urls: [ '/css/fonts.css' ] }
};
var loadSans = function() {
if (sansLoaded) return;
sansLoaded = true;
WebFontConfig.custom.families.push('Open+Sans:400,700:latin');
try {
(function() {
var wf=document.createElement('script');
wf.src = '/js/webfont.js';
wf.type='text/javascript';
wf.async='true';
var s=document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
} catch (e) {}
};
var fonts = document.querySelectorAll('nav #font - picker a . font ' );
for (var i=0; i<fonts.length; i++) {
fonts[i].addEventListener('click', function(e) {
e.preventDefault();
selectedFont = this.href.substring(this.href.indexOf(' #')+1);
$ writer . el . className = selectedFont;
document.querySelector('nav #font - picker li . selected ' ).classList.remove( ' selected ' );
this.parentElement.classList.add('selected');
H.set('{{if .Editing}}draft{{.Post.Id}}font{{else}}padFont{{end}}', selectedFont);
if (selectedFont == 'sans') {
loadSans();
}
});
}
var selectedFont = H.get('{{if .Editing}}draft{{.Post.Id}}font{{else}}padFont{{end}}', '{{.Post.Font}}');
var sfe = document.querySelector('nav #font - picker a . font . ' +selectedFont);
if (sfe != null) {
sfe.click();
}
var doneTyping = function() {
if (draftDoc == 'lastDoc' || $ writer . el . value != origDoc) {
H.save( $ writer , draftDoc);
2020-06-11 17:45:12 +02:00
if (!defaultTimeSet) {
var lastLocalPublishStr = localStorage.getItem(draftDoc+'-published');
if (lastLocalPublishStr == null || lastLocalPublishStr == '') {
localStorage.setItem(draftDoc+'-published', updatedStr);
}
defaultTimeSet = true;
}
2018-11-08 06:11:42 +01:00
updateWordCount();
}
};
window.addEventListener('beforeunload', function(e) {
if (draftDoc != 'lastDoc' && $ writer . el . value == origDoc) {
H.remove(draftDoc);
2020-06-11 17:45:12 +02:00
H.remove(draftDoc+'-published');
2018-11-08 06:11:42 +01:00
} else if (!justPublished) {
doneTyping();
}
});
try {
(function() {
var wf=document.createElement('script');
wf.src = '/js/webfont.js';
wf.type='text/javascript';
wf.async='true';
var s=document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
} catch (e) {
// whatevs
}
</script>
<link href="/css/icons.css" rel="stylesheet">
</body>
</html>{{end}}