Skip to content
saksham10arora-dotcomPublic

About

Pins a YouTube lecture in full screen. Escape does nothing; getting out takes a deliberate hold.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

Latch
██╗      █████╗ ████████╗ ██████╗██╗  ██╗
██║     ██╔══██╗╚══██╔══╝██╔════╝██║  ██║
██║     ███████║   ██║   ██║     ███████║
██║     ██╔══██║   ██║   ██║     ██╔══██║
███████╗██║  ██║   ██║   ╚██████╗██║  ██║
╚══════╝╚═╝  ╚═╝   ╚═╝    ╚═════╝╚═╝  ╚═╝

Pins a lecture or a reading in full screen. Escape does nothing.

Most blockers ask you to be disciplined at the exact moment you are not. Latch is built for the version of you who wants to quit.

License: MIT Chrome MV3 Tests Escape surface

The lock screen assembling: the gauge draws to how far into the lecture you already are

The moment it exists for

You are forty minutes into a lecture. It gets hard. Your hand reaches for Cmd-T before you have decided anything.

Latch is what happens next. Press Escape and nothing happens.

The same is true of the reading it set. A course is a video and a PDF, and the PDF is usually the part you quit first.


Where it works

48 platforms:

Video and the big MOOCs · YouTube, Udemy, Coursera, edX, Udacity, FutureLearn, Codecademy, Pluralsight, Skillshare, DataCamp, Educative, Alison, MasterClass, Domestika, LinkedIn Learning, O'Reilly

Developer platforms · Frontend Masters, egghead.io, Laracasts, Scrimba, Treehouse, Vue School, LeetCode, Code with Mosh

India · NPTEL, SWAYAM, Unacademy, Physics Wallah, Vedantu, BYJU'S, Doubtnut, Testbook, Scaler, Coding Ninjas, upGrad, Great Learning, Simplilearn

Universities and open courseware · MIT OpenCourseWare, Stanford Online, Khan Academy, Brilliant

Course hosting · Teachable, Thinkific, Kajabi, Podia, Maven, Vimeo

Readings · Google Drive's file viewer, and any PDF open in Chrome's own viewer, including ones on your disk.

LinkedIn, O'Reilly and Google Drive are scoped to /learning/, /library/ and /file/, so the extension never asks for the rest of any of them. Drive especially: it gets the file viewer, not your files.

And anywhere else. The lock itself is site-agnostic: Keyboard Lock, fullscreenchange and the wall are browser features, not YouTube features, so only four things ever needed a site to be named, and three of them have a generic answer. An unlisted platform still locks, matching on accessibility labels (aria-label="Full screen") rather than class names, because a label is a contract a player is unlikely to break while .ytp-fullscreen-button is an implementation detail that moves.

A site entry in src/persuade.js is therefore an optimisation, not a requirement. Adding one is a few lines, and nothing breaks without it.

Readings

A PDF is not a video, but it is the other half of most courses, so Latch locks it too. Chrome renders a PDF as an ordinary document: the content script runs in it, the wall covers it, and Escape still reaches the page even while the PDF itself has focus.

Google Drive is the same idea by a different route. Its viewer is a web app rather than Chrome's, so the page reports itself as HTML and the PDF detection cannot see it; the site adapter says so instead. Shared course notes usually live there, which makes it worth naming.

Two things differ. A PDF has no player, so there is no full screen button to press and nothing for the lock to wait for; Latch puts its own Lock this reading button in the corner instead, and pressing it is what engages the lock. And there is no progress to show, because the viewer runs in a frame the extension is not allowed to read, so the wall drops its gauge rather than displaying a ring stuck at zero.

Local files need one extra step: chrome://extensions → Latch → Details → turn on Allow access to file URLs. Chrome will not grant it silently, and without it a file:// PDF is invisible to the extension.

What it stops

You press What happens
Escape nothing
Cmd-R, Cmd-L nothing
Cmd-T, Cmd-W, Cmd-N, Cmd-1..9 nothing
f, the player's full screen button nothing
a different tab you are put back
an address that is not YouTube you are put back
closing the tab it reopens, still locked
holding Escape for two seconds the lock screen

The video pauses too, so a lecture is never playing to an empty room behind the lock screen.

How Escape is blocked

navigator.keyboard.lock(["Escape"]), the Keyboard Lock API that remote-desktop and cloud-gaming pages use. While it is held in full screen, Escape arrives as an ordinary keydown and does not exit full screen.

Holding Escape for two seconds still forces full screen off, and no API can remove that. It is a browser guarantee and it should be: a page able to trap someone in full screen with no way out would be a dangerous thing to build.


Getting out

A hold, not a click, because a click is a reflex and eight seconds is not. Optionally a phrase to retype as well. Letting go resets the timer, so it cannot be chipped away at in bursts, and a correct phrase cannot skip the hold.

The toolbar popup cannot end an engaged lock. Neither can the keyboard shortcut. Every route out has to cost the same thing, or the cheapest one becomes the only one anybody uses.

While you hold it, the screen argues. It uses what the page actually knows: minutes watched, minutes left, and how many times you have already bounced off it.

You are 34 minutes in.

The expensive part is already paid. Starting is what costs you, and you did that 34 minutes ago.

17 days. This is the one that breaks it.

Streaks do not end on the hard days. They end on an ordinary Tuesday when someone decides one skip does not count.

Deliberately unflattering rather than motivational. Motivational copy stops working on the second reading, and copy that shames you makes the extension something you delete.


Every way out, written down

ESCAPES.md is the full audit: each route, what closes it, and which are deliberately left open.

It exists because eight real bypasses were found by using this, and patching them one at a time kept missing the class each belonged to. Three patterns account for all of them:

  1. Guards gated on inFullscreen(), which is false exactly when the lock screen is up, leaving the screen shown to someone actively trying to leave as the least protected part of the extension.
  2. Load order. After a reload the lock screen goes up before YouTube has built its player, so anything done to the page once may need doing again.
  3. Races. Closing the locked tab reopens it, and two guards read the momentarily missing tab as "the session is over" and disarmed it. Exactly one place may end a session.

Deliberately still open: holding Escape, removing the extension, quitting Chrome, Cmd-Tab, incognito, other extensions, another browser. A lock with no way out is a dangerous thing to build.


Install

Not on the Chrome Web Store yet.

git clone https://github.com/saksham10arora-dotcom/latch.git

chrome://extensions → enable Developer mode → Load unpacked → pick the cloned folder.

Then play a lecture, go full screen, and press Option-Shift-L.

For a reading, arm Latch and press the Lock this reading button it puts in the corner. A PDF has no full screen control of its own, so that button is the way in.

If the shortcut does nothing, another extension has claimed it. The popup reads the binding back from Chrome and will tell you; set your own at chrome://extensions/shortcuts.

Turn on "Allow in Incognito" while you are there, or a private window is a clean way out. Turn on "Allow access to file URLs" too if you read PDFs off your own disk.


Development

npm install
npm test               # 46 tests
bash scripts/package.sh   # -> build/latch.zip for the Web Store

All logic that can be tested without a browser lives in src/persuade.js. The tests import it the same way Chrome loads it, as a classic script attaching to globalThis, so a change that breaks the extension breaks the suite.

The service worker deliberately does not call importScripts. A worker registers its listeners by running top to bottom, so anything that throws first means chrome.tabs.onActivated is never registered and the guard silently does not exist. The few values it needs are inlined, and tests assert the copy has not drifted from the module.

Most likely to rot: the YouTube selectors in src/lock.js. Those are YouTube's own class names and they move.


Privacy

No network requests, no analytics, nothing leaves your machine. storage holds your own settings and the lock state. tabs is what lets the lock return you to the lecture tab and reopen it if it is closed.

The full policy, including exactly which six values are stored and what is read from a page, is in PRIVACY.md.


Known limits

  • Chrome and Chromium only. The logic ports; the manifest needs a Firefox variant.
  • PDFs on arbitrary websites are not covered. Latch locks PDFs on the platforms above and on file://. Reaching every PDF on the web would mean requesting access to every site on the web, which is a much larger permission than a focus timer has any business holding.
  • A determined person gets around all of it. Latch raises the cost of a distraction. It is not a prison, and it should not be.

MIT. Built with ❤️ by Saksham Arora.

About

Pins a YouTube lecture in full screen. Escape does nothing; getting out takes a deliberate hold.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages