Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔔 Notify when all cells completed #2531

Merged
merged 1 commit into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/components/BottomRightPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export let BottomRightPanel = ({ desired_doc_query, on_update_doc_query, noteboo
`
}

const useDelayedTruth = (/** @type {boolean} */ x, /** @type {number} */ timeout) => {
export const useDelayedTruth = (/** @type {boolean} */ x, /** @type {number} */ timeout) => {
const [output, set_output] = useState(false)

useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const first_true_key = (obj) => {
*/

const url_logo_big = document.head.querySelector("link[rel='pluto-logo-big']")?.getAttribute("href") ?? ""
const url_logo_small = document.head.querySelector("link[rel='pluto-logo-small']")?.getAttribute("href") ?? ""
export const url_logo_small = document.head.querySelector("link[rel='pluto-logo-small']")?.getAttribute("href") ?? ""

/**
* @typedef EditorProps
Expand Down
84 changes: 84 additions & 0 deletions frontend/components/NotifyWhenDone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { html, useEffect, useState } from "../imports/Preact.js"

import { cl } from "../common/ClassTable.js"
import { is_finished, total_done } from "./ProcessTab.js"
import { useDelayedTruth } from "./BottomRightPanel.js"
import { url_logo_small } from "./Editor.js"

/**
* @param {{
* status: import("./Editor.js").StatusEntryData,
* }} props
*/
export let NotifyWhenDone = ({ status }) => {
const all_done = Object.values(status.subtasks).every(is_finished)

const [enabled, setEnabled] = useState(false)

useEffect(() => {
if (enabled && all_done) {
console.log("all done")

/** @type {Notification?} */
let notification = null

let timeouthandler = setTimeout(() => {
setEnabled(false)
let count = total_done(status)
notification = new Notification("Pluto: notebook ready", {
tag: "notebook ready",
body: `✓ All ${count} steps completed`,
lang: "en-US",
dir: "ltr",
icon: url_logo_small,
})
notification.onclick = (e) => {
parent.focus()
window.focus()
notification?.close()
}
}, 3000)

const vishandler = () => {
if (document.visibilityState === "visible") {
notification?.close()
}
}
document.addEventListener("visibilitychange", vishandler)
document.body.addEventListener("click", vishandler)

return () => {
notification?.close()

clearTimeout(timeouthandler)
document.removeEventListener("visibilitychange", vishandler)
document.body.removeEventListener("click", vishandler)
}
}
}, [all_done])

const visible = useDelayedTruth(!all_done, 2500) || enabled

return html`
<div class=${cl({ visible, "notify-when-done": true })}>
<label
>${"Notify when done"}
<input
type="checkbox"
checked=${enabled}
disabled=${!visible}
onInput=${(e) => {
if (e.target.checked) {
Notification.requestPermission().then((r) => {
console.log(r)
setEnabled(r === "granted")
e.target.checked = r === "granted"
})
} else {
setEnabled(false)
}
}}
/></label>
</div>
`
}
2 changes: 2 additions & 0 deletions frontend/components/ProcessTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { cl } from "../common/ClassTable.js"
import { prettytime, useMillisSinceTruthy } from "./RunArea.js"
import { DiscreteProgressBar } from "./DiscreteProgressBar.js"
import { PkgTerminalView } from "./PkgTerminalView.js"
import { NotifyWhenDone } from "./NotifyWhenDone.js"

/**
* @param {{
Expand All @@ -23,6 +24,7 @@ export let ProcessTab = ({ status, notebook, backend_launch_logs, my_clock_is_ah
nbpkg=${notebook.nbpkg}
backend_launch_logs=${backend_launch_logs}
/>
<${NotifyWhenDone} status=${status} />
</section>
`
}
Expand Down
1 change: 1 addition & 0 deletions frontend/dark_color.css
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
--process-busy: #ffcd70;
--process-finished: hsl(126deg 30% 60%);
--process-undefined: rgb(151, 151, 151);
--process-notify-bg: hsl(0 0% 21%);

/*footer*/
--footer-color: #cacaca;
Expand Down
57 changes: 52 additions & 5 deletions frontend/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,8 @@ pluto-helpbox > section {
height: 100%;
overflow: auto;
padding: 10px;
display: flex;
flex-direction: column;
}

pluto-helpbox > header {
Expand Down Expand Up @@ -2384,16 +2386,12 @@ pl-status {
display: flex;
flex-direction: column;
border-radius: 0.2em;
/* margin: 0.3em; */
--indent: 0.7rem;
margin-left: var(--indent);
border-left: 3px solid transparent;
margin-top: 0.4em;
overflow: hidden;
/* background: var(--status-color); */
/* transition: max-height 1s linear; */
/* max-height: 30px; */
flex: 1 0 auto;
flex: 0 0 auto;
}

pl-status::before {
Expand Down Expand Up @@ -2529,6 +2527,55 @@ pl-status pkg-terminal {
margin-left: var(--indent);
}

pluto-helpbox.helpbox-process > section {
padding-bottom: 3.6rem; /* to make space for the notification toggle */
}

.notify-when-done {
position: absolute;
bottom: 0.3em;
right: 0;
left: 0;

font-family: var(--system-ui-font-stack);
font-weight: bold;
font-size: 0.8rem;
transition: opacity 0.2s;
display: flex;
justify-content: center;
opacity: 0;
user-select: none;
}

.notify-when-done.visible {
opacity: 1;
}

.notify-when-done.visible label {
cursor: pointer;
}

.notify-when-done label {
display: flex;
align-items: center;
background: var(--process-notify-bg);
padding: 0.3em 0.6em;
border-radius: 1000px;
box-shadow: 0px 3px 5px #0000003b;
}

.notify-when-done label::before {
content: "";
display: inline-block;
width: 1em;
height: 1em;
background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/notifications-outline.svg");
background-size: contain;
filter: var(--image-filters);
margin-bottom: -0.2em;
margin-right: 0.3em;
}

/* FOOTER */

footer {
Expand Down
1 change: 1 addition & 0 deletions frontend/light_color.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
--process-busy: #ffcd70;
--process-finished: hsl(126deg 30% 60%);
--process-undefined: rgb(151, 151, 151);
--process-notify-bg: hsl(44.86deg 50% 94%);

/*footer*/
--footer-color: #333333;
Expand Down