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

feat: Feedback on notebook run completion #1634

Merged
merged 8 commits into from
Jun 19, 2024
Merged

feat: Feedback on notebook run completion #1634

merged 8 commits into from
Jun 19, 2024

Conversation

wasimsandhu
Copy link
Collaborator

@wasimsandhu wasimsandhu commented Jun 18, 2024

📝 Summary

Gives user feedback on notebook run completion via dynamic favicon and optional system notifications.

Addresses feature request in #1039.

🔍 Description of Changes

Dynamic favicon

Favicon changes to indicate whether a notebook is running, and whether the run completed successfully or encountered errors.

This favicon persists until the user navigates back to their notebook, or resets back to the marimo favicon after 3 seconds if the notebook is in focus.

Favicon when notebook is running:

blue play

Favicon when a run completed successfully:

green check

Favicon when a run produced errors:

red x

Notifications

Implemented by @mscolnick, more info in this comment.

Screenshot 2024-06-18 at 7 08 46 PM Screenshot 2024-06-18 at 7 09 16 PM

📋 Checklist

  • I have read the contributor guidelines.
  • For large changes, or changes that affect the public API: this change was discussed or approved through an issue, on Discord, or the community discussions (Please provide a link if applicable).
  • I have added tests for the changes made.
  • I have run the code and verified that it works as expected.

📜 Reviewers

@mscolnick

Copy link

vercel bot commented Jun 18, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
marimo-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2024 2:44am
marimo-storybook ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2024 2:44am

@wasimsandhu
Copy link
Collaborator Author

wasimsandhu commented Jun 18, 2024

@mscolnick My changes work in development mode, but I can't get the favicons to appear when running in prod. Tried clearing my cache and testing in incognito, but no luck. Any ideas?

@wasimsandhu wasimsandhu changed the title feat: Notifications for run feedback feat: Feedback on notebook run completion Jun 18, 2024
@akshayka
Copy link
Contributor

Thanks for this, @wasimsandhu!

Add optional app (user?) settings for audio and system notifications on run completion.

I'd say to do just the favicon for now. I'd prefer not to add another app setting (unless people really want it).


useEventListener(document, "visibilitychange", (_) => {
resetFaviconIfComplete();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you we move this logic to its own react component
<DynamicFavicon/>

it could be in the same file, but just nicer to encapsulate the logic

document.getElementsByTagName("head")[0].append(favicon);
}

const favicons: Record<string, string> = useMemo(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesnt need live in the react component.

it could be at the module level:

const FAVICON_ROUTES = {
    idle: "./favicon.ico",
    success: "./circle-check.ico",
    running: "./circle-play.ico",
    error: "./circle-x.ico",
}

};
}, [isRunning, errors, favicon, favicons, resetFaviconIfComplete]);

useEventListener(document, "visibilitychange", (_) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you document how you want this to work?

i think i mentioned we could use document.visibilityState/visibilitychange, but that was so when the editor is active, we arent flickering the favicon and only change it when the editor is out of focus. that was only a suggestion, but up-to-you what you feel feels right.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also - im not sure this actually solves the ticket yet. i think what might happen with the above is:

  1. goes to running
  2. shows the success
  3. then clears after 3 seconds

If you miss that 3 second window, you don't really get the feedback. Maybe the logic could be:

  1. goes to running
  2. shows the success
  3. then clears after 3 seconds ONLY if the document is focused, otherwise keep it there
  4. clear when the user comes back into focus (could be after 3 seconds or right away)

also worth documenting this logic in a comment on the DynamicFavicon component

Copy link
Collaborator Author

@wasimsandhu wasimsandhu Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll add some comments in the file.

You're right, the favicon is reset after 3 seconds if the page is visible, but remains if it is not. I agree that it should persist if the document is not in focus.

return () => {
favicon.href = favicons.idle;
};
}, [isRunning, errors, favicon, favicons, resetFaviconIfComplete]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can probably inline resetFaviconIfComplete, because we will want to clear the timeout too on the returned unsubscribe

  useEffect(() => {
    if (isRunning) {
      FAVICONS.href = favicons.running;
      return;
    }
    favicon.href = errors.length > 0 ? FAVICONS.error : FAVICONS.success;
    // Reset back to idle after 3 seconds
    const timeout = setTimeout(() => {
        favicon.href = FAVICONS.idle;
      }, 3000);
    return () => {
      favicon.href = FAVICONS.idle;
      clearTimeout();
    };
  }, [isRunning, errors.length]);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch thanks!

@mscolnick
Copy link
Contributor

if this feels right, you could also use the native browser notification. this way you dont need to add anything to user settings, and they can configure it on the first try (and if they deny access, it wont happen again)

function maybeSendNotification() {
  // If in focus, skip
  if (document.visibilityState === "visible") {
    return;
  }

  const sendNotification = () => {
    if (succeeded) {
      const notification = new Notification("Execution completed", {icon: icon});
    } else {
      const notification = new Notification("Execution failed", {icon: icon}););
    }
  }

  if (!("Notification" in window)) {
    // Skip no support
  } else if (Notification.permission === "granted") {
    // Permission already granted
    sendNotification();
  } else if (Notification.permission !== "denied") {
    // We need to ask the user for permission
    Notification.requestPermission().then((permission) => {
      // If the user accepts, let's create a notification
      if (permission === "granted") {
        sendNotification();
      }
    });
  }
}

@mscolnick
Copy link
Contributor

@wasimsandhu for it working in production - you might need to add those assets to here:
https://github.com/marimo-team/marimo/blob/main/marimo/_server/api/endpoints/assets.py#L93-L98

@mscolnick
Copy link
Contributor

nice! looks great!

Copy link

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.6.20-dev18

@wasimsandhu wasimsandhu deleted the ws/enhancements branch June 19, 2024 17:25
@Light2Dark Light2Dark mentioned this pull request Dec 19, 2024
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants