From 03a071f04c4e3c5f9d3c1c038c26cd938b069a8b Mon Sep 17 00:00:00 2001 From: Nicholas Jitkoff Date: Sun, 31 Jul 2022 13:05:20 -0700 Subject: [PATCH] Add timers --- docs/render.js | 1 + docs/render/recipe.css | 134 +++++++++++++++++++++++++---------- docs/render/recipe.js | 92 +++++++++++++++++++++--- docs/render/recipe/beep.mp4 | Bin 0 -> 2123 bytes docs/render/recipe/beep2.mp4 | Bin 0 -> 4309 bytes 5 files changed, 181 insertions(+), 46 deletions(-) create mode 100644 docs/render/recipe/beep.mp4 create mode 100644 docs/render/recipe/beep2.mp4 diff --git a/docs/render.js b/docs/render.js index 9afc11d..dcac286 100644 --- a/docs/render.js +++ b/docs/render.js @@ -79,6 +79,7 @@ window.addEventListener("message", function(e) { }, false); function QRCodeURL(url, options) { + if (url.length > 2953) return undefined; let size = options?.size ?? 547; let errorCorrection = options?.correction ?? 'L'; let margin = options?.margin?.toString() || "1"; diff --git a/docs/render/recipe.css b/docs/render/recipe.css index eff3ca7..16370a6 100644 --- a/docs/render/recipe.css +++ b/docs/render/recipe.css @@ -14,8 +14,11 @@ body { rgba(16, 12, 12, 0.54); --hover-background-color: rgba(16, 12, 12, 0.07); - --image-placeholder-color: var(--hover-background-color); + --image-placeholder-color: + var(--hover-background-color); --background-color:white; +--alt-text-color: + rgb(0, 118, 173); } .thumbnail { @@ -39,18 +42,62 @@ body { /* text-decoration:underline; */ } -.time-button { - /* background-color:cyan; */ - white-space: nowrap; - border-radius:1em; - /* padding:0 0.3em; */ - /* border:1px solid currentColor; */ - text-decoration:underline; - text-decoration-style: dotted; + +@media screen { + .timer { + /* background-color:cyan; */ + white-space: nowrap; + border-radius: 2px; + padding: 0 0.1em; + margin: 0 -0.1em; + /* text-decoration:underline; */ + text-decoration-style: dotted; + box-sizing: border-box; + /* color: var(--background-color); */ + + border-bottom:1px solid transparent; + border-bottom-color: currentColor; + /* background-color: var(--text-color); */ + } + + .timer:hover, + .timer.active { + color: var(--background-color); + background-color:var(--text-color); + z-index:100; + /* border:1px solid currentColor; */ + position:relative; + + border-bottom-color: transparent; + } + + .timer.active .label{ + opacity:0.0; + } + .timer .countdown{ + position: + absolute; + display: + none; + width: 100%; + text-align: center; + left: 0; + } + .timer.active .countdown { + display:inline-block; + } +} + + +@media print { + .timer { + font-weight:800; + } } img.publisher { max-width: 5em; + max-height: 2em; /* margin-top: -0.1em; */ /* transform:scale(0.7); */ /* float: @@ -65,11 +112,11 @@ img.publisher { .columns { display: flex; - gap: 2em; + gap: 3em; margin-bottom: 4em; align-content: center; justify-content: center; - flex-direction: row; + flex-direction: row-reverse; margin-top: 1em; } @@ -136,15 +183,29 @@ span.number { /* background: black; */ } -.complete span.number, -li:hover span.number { - color:transparent; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='48' width='48'%3E%3Cpath d='M18.9 36.9 6.5 24.5 9.9 21.1 18.9 30.1 38.05 10.95 41.45 14.35Z'/%3E%3C/svg%3E"); background-size:cover; +@media screen { + .complete span.number, li:hover span.number { + color:transparent; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='48' width='48'%3E%3Cpath d='M18.9 36.9 6.5 24.5 9.9 21.1 18.9 30.1 38.05 10.95 41.45 14.35Z'/%3E%3C/svg%3E"); background-size:cover; -} -.complete span.number { - border-color:transparent; + } + .complete span.number { + border-color:transparent; + } + + .complete .noun { + color:var(--disabled-text-color); + } + .ingredient.complete, + li.complete { + text-decoration: line-through; + color:var(--disabled-text-color); + + text-decoration: line-through; + /*noinspection CssOverwrittenProperties*/ + text-decoration: rgba(0,0,0,0.75) solid 0.5px line-through; /* Ignored in CSS1/CSS2 UAs */ + } } .number.big { @@ -212,22 +273,20 @@ li:hover { .ingredients { font-weight: 600; font-size: 88%; - /* position: - sticky; */ + position: sticky; /* top: 0px; */ /* padding-top: 1.5em; */ flex: 0 1 35%; /* color: rgba(0,0,0,0.8); */ - /* color:rgb(0, 118, 173); */ + /* color: + rgb(0, 118, 173); */ } .noun { font-weight: 700; - color: var(--opaque-text-color); -} -.complete .noun { - color:var(--disabled-text-color); + color: var(--alt-text-color); } + li:hover .noun { text-decoration: 1px dotted underline; /* background-color: var(--hover-background-color); */ @@ -274,16 +333,6 @@ li:hover .noun { right; } -.ingredient.complete, -li.complete { - text-decoration: line-through; - color:var(--disabled-text-color); - -text-decoration: line-through; -/*noinspection CssOverwrittenProperties*/ -text-decoration: rgba(0,0,0,0.75) solid 0.5px line-through; /* Ignored in CSS1/CSS2 UAs */ -} - .ingredient:hover { opacity: 1.0; background-color: rgba(128, 128, 128, 0.1) @@ -291,7 +340,7 @@ text-decoration: rgba(0,0,0,0.75) solid 0.5px line-through; /* Ignored in CSS1/C .step { max-width: 80em; - cursor: pointer; + cursor: default; /* border:1px solid red; */ margin-bottom: 1em; } @@ -422,6 +471,7 @@ a.action .icon { user-select: none; /* float: left; */ display: inline-block; + -webkit-print-color-adjust: exact; } @@ -431,7 +481,7 @@ a.action .icon { min-height:100vh; } .print-hide { - display: none; + display: none !important; } @page { @@ -544,7 +594,7 @@ img.qr { width: 16px; height: 16px; } -.icon.timer { +.icon.time { background-position: -72px -16px; width: 16px; height: 16px; @@ -647,4 +697,12 @@ a.publisherlink { /* order: -2; */ /* width: 100%; */ float: left; +} + +.headerleft h1 { + max-width: 16em; +} + +span.timer.active.expired { + background-color: rgb(221, 40, 0); } \ No newline at end of file diff --git a/docs/render/recipe.js b/docs/render/recipe.js index 0111a23..30319fa 100644 --- a/docs/render/recipe.js +++ b/docs/render/recipe.js @@ -265,6 +265,7 @@ function highlightStep(e) { // el.classList.toggle("complete", ) // } if (e.target.classList.contains("noun")) return; + if (e.target.closest(".timer")) return; if (e.target.tagName == "A") return; e.target.closest("li").classList.toggle("complete") @@ -293,12 +294,67 @@ function highlightTerms(string, terms) { } function highlightTimes(string) { - const pattern = /([0-9]+) ?(minutes|hours)/g; - return string.replace(pattern, match => { - return `${match}` + const pattern = /([0-9]+)\s*(?:to|-|–)?\s*([0-9]+)?\s?(minutes?|hours?)/g; + return string.replace(pattern, (match, t1, t2, tt, offset, groups) => { + // console.log("match", t1, t2, tt) + + return `${match}` }); } +function dismissTimer(e) { + console.log(e.target); +} + +function playSound(loc) { + var audio = new Audio(loc); + // audio.play(); +} + +function startTimer(e, t1, t2) { + if (!e.startTime) { + e.startTime = new Date(); + let duration = t1 * 60 + e.endTime = new Date(e.startTime.getTime() + duration * 1000); + + console.log("end", e.endTime); + let countdownEl = e.querySelector(".countdown"); + + console.log(e, t1, t2); + e.classList.add("active") + let update = () => { + let now = new Date(); + let percent = (now - e.startTime) / 1000 / duration * 100; + // console.log("perc", (now - e.startTime)/1000 , percent, duration) + e.style.backgroundImage = `linear-gradient(to right, transparent ${percent}%, rgba(255,255,255,0.4) ${percent}%)` + let remaining = Math.round((e.endTime - now)/1000); + let expired = percent > 100; + if (expired) { + playSound("recipe/beep.mp4") + delete e.style.backgroundImage; + // clearInterval(e.interval); + remaining = -remaining; + e.classList.add("expired") + } + + let countdownString = `${expired ? "-": ""}${Math.floor(remaining / 60)}m ${remaining % 60}s` + countdownEl.innerText = countdownString; + + } + e.interval = setInterval(update, 1000) + update(); + } else { + e.interval = clearInterval(e.interval) + e.classList.remove("active"); + e.classList.remove("expired"); + + e.style.backgroundImage = ''; + delete e.startTime; + } +} + +window.startTimer = startTimer; + function share() { parent.postMessage({share:{}}, "*"); } @@ -342,7 +398,6 @@ function render() { let favicon = faviconForTitle(title) || "🍴"; parent.postMessage({title:title, favicon:favicon, image:image, description:description, wakeLock:true, updateURL:true}, "*"); description = description.split("\n").join("

") - console.log(description) // let text = instructions.join(" "); let ingredients = json.recipeIngredient; @@ -386,6 +441,24 @@ function render() { m("span.substep",{innerHTML:highlightTimes(highlightTerms(FRACTION_MAP.replace(text.trim()), terms))})) } + function stepsFromText(text) { + let steps = [] + let components = text.split(/(?<=[\.\!\?]|[\.\!\?]\)|\))\s+(?!\()/); + + let append = false; + while (components.length) { + let step = components.shift() + if (append) { + steps.push(steps.pop() + " " + step) + } else { + steps.push(step); + } + if (step.indexOf("(") >= 0) { append = true; } + if (step.includes(")")) { append = false; } + } + + return steps; + } function flattenInstructions(instruction) { if (instruction.itemListElement) { return ["= " + instruction.name].concat(flattenInstructions(instruction.itemListElement).flat()); @@ -400,7 +473,7 @@ function render() { console.log() if (reformat) { - text = text.replace(/(\.\)? )+/g,"$1\n").split("\n")///text.match( /[0-9\. ]{0,6}[^\.!\?]+[\.!\?]+/g ); + text = stepsFromText(text); } else { text = text.match( /[^\n]+/g ); } @@ -436,13 +509,16 @@ function render() { bgImg.onload = function(){ let thumbnail = document.querySelector("#thumbnail"); let thumbnailContainer = document.querySelector("#thumbnail-container"); - thumbnail.style.backgroundImage = 'url(' + bgImg.src + ')'; + thumbnail.style.backgroundImage = 'url("' + bgImg.src + '")'; thumbnail.style.filter = `blur(${thumbnailContainer.offsetHeight / bgImg.naturalHeight * 1}px)`; thumbnail.style.transform = `scale(1.1)`; setTimeout(() => thumbnail.style.opacity = 1.0, 100); }; bgImg.src = image; + console.log("image", bgImg.src) + + let qrImage = QRCodeURL(params.originalURL, {margin:0}); let originalURL = json.mainEntityOfPage?.["@id"] || json.mainEntityOfPage || json.url; document.body.appendChild( m(".recipe", {}, @@ -458,7 +534,7 @@ function render() { m(".metadata", (recipeYield) ? m("div", m("span.yield", m(".icon.servings"), recipeYield)) : null, json.totalTime ? m(".time", - m(".icon.timer"), + m(".icon.time"), json.totalTime ? m("span", formatTime(json.totalTime)) : undefined, // " (", @@ -496,7 +572,7 @@ function render() { m("section.ingredients", m("caption.ingredients-title", "Ingredients"), ingredients, - m("img.qr.print-show", {src:QRCodeURL(params.originalURL, {margin:0})}) + qrImage ? m("img.qr.print-show", {src:qrImage}) : null ), m(reformat ? "section.instructions.numbered" : "section.instructions", m("caption.ingredients-title", {onclick:() => {reformat = !reformat; render(); return false;}}, diff --git a/docs/render/recipe/beep.mp4 b/docs/render/recipe/beep.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..48c1ec42818bd79b83267fa3338c60cdcb4adb37 GIT binary patch literal 2123 zcmbtVYfw|y7G5U-0wLId;hoWlsEEijSSt+;A#lM51TYF0MIs3hOb8``VlLHGBZ7#f zD1sDQ&<>ayv8ebcIA8#!0~RXfZ=5S@^qJ7yz zs}77-_Sk+VzWaS`m-pnlK@H7|^5gkOcOwp7aLsnpl`DD98ea^2%Ua7O{gPORH@SMm zBplk+vmk9q$=_TfPrU6Cz&a2R_m%C+5Xo+#xKiU;IpZnrol64EVv{%cl@i4U# zSa)!vt>>$`gK$}udN8JbfNL(1@hUIqYPgoRfKfLRzY}Lr6$oEdx zIGN2$Aq@oY*YXD+yQezwYRca^e2f*oo{BL&utYNzEfx!+KOLwdoc&_~3yJ|cdsShq zJE<9%ovoJF=S$XML1AcXlzhSvTvp4RJG~k>jp`g(-gNI6|EXTxV8h~%`!4-=DSy$S z&Zb7~!+7+9@#x#L(mn+K08zE8tpK8BXES`yS&J~ z1q3y_pLd9l9)G`yG90i8Q+E{X>3=Zu&BQ9m(AopWQ322-#8X_X7>c9Hx>;*Y%NQp5 zD9f}dvRy2MkyeZWS%tM=bX%==-x{)R@mDG#XN9?ij*yYBzZh@3UwQ4r^Oq=hmL#vU z>GyOBl-s04990_P?iHR}lHQ+hk#oDCa@v$?Qn|+b_^HM9PrtAnwi0xl3BRi9vhZEs zlUorXranorC6+_tL#6gq&^q9sOs`E~08eGQC$c`!5`xT$80X8gJEwL}A{8KzsJY@+OVnCj})`e!26;ua{Yl?ENs}azax0 z4H_vq#Y$X#ldc$h+0CiHRZ{2%Y#>$vxItSPP~2J}*yITJ2O`^qP)*+B5cxt2Jb>

SDl_=&e~_NA7K#G0S^g?6jI~NlcXgi`b@Vys)+9 zQE%F&(4vt0uH>B4A@-8X3x%$O)BbipQmcb-M2w3*4s$O)l0~lwVS25Y7)zKC0=8sp z!nEIlncx4^YXB_u7rm@@w-1Ce95V;7g5hT*|JySmEda!5sZ5rQ4kD3erwZ{C-KS(9 z!3{vmMHf;D0`l`)}XuH<|yW2&iCKktx`Lf?E_jj6Jb8J?B-+X@k&3DE4E9JPLV6*#$mtmZ$>W- zzF8b^j!6J2?!d1B!A~R?%5gzdsZ=hAO%T)AG;l!LU^G+YA=sFkA;Qp{!9lK27)y}G zmo-O4h=7jTC*cAC_rHo6nTcXbV`TOZ)fkKV5NnZritH<7Rmkd*okm8JE0XZp;K0}N zKxW7iDg=n1N<~IS5?uZ|Yji)a=Z*)BXcJ51_*2`o5&!)T6=ub1ruVGy@nyaa;Tb-w-U)u~_&>#e E0Z9O#*Z=?k literal 0 HcmV?d00001 diff --git a/docs/render/recipe/beep2.mp4 b/docs/render/recipe/beep2.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..394f010056c93e562b90490099a3f34378854259 GIT binary patch literal 4309 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 literal 0 HcmV?d00001