Fix puzzles on iOS

This commit is contained in:
Neale Pickett 2018-09-21 23:45:28 +00:00
parent 54efa779af
commit 12f5d4e2db
3 changed files with 115 additions and 78 deletions

View File

@ -7,17 +7,6 @@
<link rel="icon" href="res/icon.svg" type="image/svg+xml"> <link rel="icon" href="res/icon.svg" type="image/svg+xml">
<link rel="icon" href="res/icon.png" type="image/png"> <link rel="icon" href="res/icon.png" type="image/png">
<script> <script>
function resize() {
let frame = document.getElementById("body");
frame.height = frame.contentDocument.documentElement.scrollHeight;
}
function render(obj, base) {
let frame = document.getElementById("body");
let html = "<base href='" + base + "'><link rel='stylesheet' href='../../../basic.css'>" + obj.body;
frame.addEventListener("load", resize);
frame.srcdoc = html;
}
function init() { function init() {
let params = new URLSearchParams(window.location.search); let params = new URLSearchParams(window.location.search);
let categoryName = params.get("cat"); let categoryName = params.get("cat");
@ -31,7 +20,16 @@ function init() {
.then(function(resp) { .then(function(resp) {
return resp.json(); return resp.json();
}).then(function(obj) { }).then(function(obj) {
render(obj, base); document.getElementById("puzzle").innerHTML = obj.body;
document.getElementById("authors").textContent = obj.authors.join(", ");
for (let fn of obj.files) {
let li = document.createElement("li");
let a = document.createElement("a");
a.href = base + fn;
a.innerText = fn;
li.appendChild(a);
document.getElementById("files").appendChild(li);
}
}).catch(function(err) { }).catch(function(err) {
console.log("Error", err); console.log("Error", err);
}); });
@ -39,6 +37,33 @@ function init() {
document.querySelector("body > h1").innerText = categoryName + " " + points document.querySelector("body > h1").innerText = categoryName + " " + points
document.querySelector("input[name=cat]").value = categoryName; document.querySelector("input[name=cat]").value = categoryName;
document.querySelector("input[name=points]").value = points; document.querySelector("input[name=points]").value = points;
function mutated(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type == 'childList') {
for (let e of mutation.addedNodes) {
console.log(e);
for (let se of e.querySelectorAll("[src],[href]")) {
se.outerHTML = se.outerHTML.replace(/(src|href)="([^/]+)"/i, "$1=\"" + base + "$2\"")
console.log(se.outerHTML);
}
console.log(e.querySelectorAll("[src]"));
}
console.log(mutation.addedNodes);
} else {
console.log(mutation);
}
}
}
let puzzle = document.getElementById("puzzle");
let observerOptions = {
childList: true,
attributes: true,
subtree: true,
};
window.observer = new MutationObserver(mutated);
observer.observe(puzzle, observerOptions);
} }
document.addEventListener("DOMContentLoaded", init); document.addEventListener("DOMContentLoaded", init);
</script> </script>
@ -46,7 +71,9 @@ document.addEventListener("DOMContentLoaded", init);
<body> <body>
<h1>Puzzle</h1> <h1>Puzzle</h1>
<section> <section>
<iframe seamless id="body">Loading...</iframe> <div id="puzzle">Loading...</div>
<ul id="files"></ul>
<p>Puzzle by <span id="authors"></span></p>
</section> </section>
<form action="answer" method="post"> <form action="answer" method="post">
<input type="hidden" name="cat"> <input type="hidden" name="cat">

View File

@ -119,20 +119,6 @@ func (ctx *Instance) tidy() {
// Do they want to reset everything? // Do they want to reset everything?
ctx.MaybeInitialize() ctx.MaybeInitialize()
// Skip if we've expired
untilspec, err := ioutil.ReadFile(ctx.StatePath("until"))
if err == nil {
until, err := time.Parse(time.RFC3339, string(untilspec))
if err != nil {
log.Printf("Unparseable date in until file: %v", until)
} else {
if until.Before(time.Now()) {
log.Print("until file time reached, suspending maintenance")
return
}
}
}
// Refresh all current categories // Refresh all current categories
for categoryName, mb := range ctx.Categories { for categoryName, mb := range ctx.Categories {
if err := mb.Refresh(); err != nil { if err := mb.Refresh(); err != nil {
@ -216,13 +202,34 @@ func (ctx *Instance) collectPoints() {
} }
} }
func (ctx *Instance) isEnabled() bool {
// Skip if we've been disabled
if _, err := os.Stat(ctx.StatePath("disabled")); err == nil {
log.Print("Suspended: disabled file found")
return false
}
untilspec, err := ioutil.ReadFile(ctx.StatePath("until"))
if err == nil {
untilspecs := strings.TrimSpace(string(untilspec))
until, err := time.Parse(time.RFC3339, untilspecs)
if err != nil {
log.Printf("Suspended: Unparseable until date: %s", untilspec)
return false
}
if until.Before(time.Now()) {
log.Print("Suspended: until time reached, suspending maintenance")
return false
}
}
return true
}
// maintenance is the goroutine that runs a periodic maintenance task // maintenance is the goroutine that runs a periodic maintenance task
func (ctx *Instance) Maintenance(maintenanceInterval time.Duration) { func (ctx *Instance) Maintenance(maintenanceInterval time.Duration) {
for { for {
// Skip if we've been disabled if ctx.isEnabled() {
if _, err := os.Stat(ctx.StatePath("disabled")); err == nil {
log.Print("disabled file found, suspending maintenance")
} else {
ctx.tidy() ctx.tidy()
ctx.collectPoints() ctx.collectPoints()
ctx.generatePuzzleList() ctx.generatePuzzleList()

View File

@ -333,61 +333,64 @@ func staticPuzzleList(w http.ResponseWriter) {
<div id="puzzles"></div> <div id="puzzles"></div>
</section> </section>
<script> <script>
function render(obj) {
puzzlesElement = document.createElement('div');
let cats = [];
for (let cat in obj) {
cats.push(cat);
console.log(cat);
}
cats.sort();
for (let cat of cats) {
let puzzles = obj[cat];
let pdiv = document.createElement('div');
pdiv.className = 'category';
let h = document.createElement('h2');
pdiv.appendChild(h);
h.textContent = cat;
let l = document.createElement('ul');
pdiv.appendChild(l);
for (var puzzle of puzzles) {
var points = puzzle[0];
var id = puzzle[1];
var i = document.createElement('li');
l.appendChild(i);
if (points === 0) {
i.textContent = "✿";
} else {
var a = document.createElement('a');
i.appendChild(a);
a.textContent = points;
a.href = "puzzle.html?cat=" + cat + "&points=" + points + "&pid=" + id;
}
}
puzzlesElement.appendChild(pdiv);
document.getElementById("puzzles").appendChild(puzzlesElement);
}
}
function init() { function init() {
fetch("puzzles.json") let params = new URLSearchParams(window.location.search);
let categoryName = params.get("cat");
let points = params.get("points");
let puzzleId = params.get("pid");
let base = "content/" + categoryName + "/" + puzzleId + "/";
let fn = base + "puzzle.json";
fetch(fn)
.then(function(resp) { .then(function(resp) {
return resp.json(); return resp.json();
}).then(function(obj) { }).then(function(obj) {
render(obj); document.getElementById("puzzle").innerHTML = obj.body;
document.getElementById("authors").textContent = obj.authors.join(", ");
for (let fn of obj.files) {
let li = document.createElement("li");
let a = document.createElement("a");
a.href = base + fn;
a.innerText = fn;
li.appendChild(a);
document.getElementById("files").appendChild(li);
}
}).catch(function(err) { }).catch(function(err) {
console.log("Error", err); console.log("Error", err);
}); });
document.querySelector("body > h1").innerText = categoryName + " " + points
document.querySelector("input[name=cat]").value = categoryName;
document.querySelector("input[name=points]").value = points;
function mutated(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type == 'childList') {
for (let e of mutation.addedNodes) {
console.log(e);
for (let se of e.querySelectorAll("[src],[href]")) {
se.outerHTML = se.outerHTML.replace(/(src|href)="([^/]+)"/i, "$1=\"" + base + "$2\"")
console.log(se.outerHTML);
}
console.log(e.querySelectorAll("[src]"));
}
console.log(mutation.addedNodes);
} else {
console.log(mutation);
}
}
} }
let puzzle = document.getElementById("puzzle");
let observerOptions = {
childList: true,
attributes: true,
subtree: true,
};
window.observer = new MutationObserver(mutated);
observer.observe(puzzle, observerOptions);
}
document.addEventListener("DOMContentLoaded", init); document.addEventListener("DOMContentLoaded", init);
</script> </script>
`, `,