Promote develop to main: the kitchen can make a sound - #854
Merged
Merged
Conversation
The tones are synthesised in the main process and handed to the page as data: WAV URLs, so that a till with no internet and no sound files on disk can still make a noise. helmet's defaults do not name media-src, so it fell back to default-src 'self', and the browser refused all of them. Found in a customer machine's log, where the new order alarm had been mute since the header was tightened: Loading media from 'data:audio/wav;base64,...' violates the following Content Security Policy directive: "default-src 'self'". Note that 'media-src' was not explicitly set, so 'default-src' is used as a fallback. The action has been blocked. This is the failure that looks like success: a console warning nobody reads, and a symptom of silence in a room where silence is expected. The kitchen announcement could not have been heard whatever else was fixed. data: only, and media only. A data: URL cannot reach the network and cannot execute, so the worst a bad one does is make a noise.
The announcement shipped with no way to turn it on. The setting was real
and the IPC was real, and the only way to reach either was to open the
developer console on the machine at the pass and type
posnic.kitchenCall.set({ ting: true, speak: true })
Nobody was going to do that, so nobody did, and a finished feature sat
switched off for its whole life. A setting nobody can find is not a
setting.
Two switches on Core Settings, beside the auto-focus ones and stored the
same way: per machine, saved immediately, because somebody flipping this
is standing next to the speaker waiting to hear the difference. Hidden
outside the desktop app, where there is no bridge behind it - a dead
control is worse than an absent one.
And a Test button, which is the point of the block. Until now the only
way to learn whether a kitchen would hear anything was to send it a real
order, which is why both faults found in this feature were found by
reading a log rather than by listening. It goes down the road a real
ticket takes: the same switches, the same tone, the same sentence, the
same window, and it says why when nothing happened.
Owner: "make female voice. more casual than machine voice. indian accent?" A SpeechSynthesisVoice carries a name and a language and nothing else, so the only way to ask for a particular voice is by name. The plain language match picked Ravi, the male half of the Windows en-IN pair, purely because Windows enumerates him first. Both voices satisfied "en-IN", nothing was wrong, and the wrong voice came out anyway. Now the accent is chosen first and the voice within it second, so an Indian woman beats a British one: the dish names are the whole point, and a name not on the list falls through to whatever that language does offer rather than failing. Delivery off the flat baseline as well, and kept close to normal on purpose. Past about 1.15 a synthesised voice stops sounding relaxed and starts sounding like a cartoon, which a kitchen laughs at twice and then ignores. Verified on this machine under Electron: it now picks Microsoft Heera, English (India), where it picked Ravi before.
…-a-sound The kitchen can actually make a sound
Owner: "beep sound is not good. i want like new order came. make it good. not beep." He was right, and the reason was in the generator: a plain sine contains nothing but its fundamental, which is what a beep is. Two things make a struck object sound struck and that tone had neither. The new one carries partials above the note and an envelope that decays from the instant it is hit. Owner: "First bell is we got new order. I want one bell for each line item before read it." The opening and the plate count are about the ticket; everything after is a dish and gets a smaller tap in front of it. Where that boundary falls is decided beside the words and travels with them, so the page never guesses by counting sentences - a guess that breaks the first time the wording moves. Owner: "how about user picks the bell sound as choice how you gave me. also give choice voice also." Three arrival bells, three taps, and the voices the machine has, each with its own Play button, because nobody can choose a sound from its name. A kitchen with a fryer roaring needs a different bell from a quiet dining room and that is not a decision to make once, in one file, for every shop. Owner: "different countries might need different voice and accent." The voice is stored by name and an empty name means the best one here, so a machine that lacks the chosen voice falls back rather than going silent. A downloaded voice pack later adds another name to the same list. Everything merges onto what is stored: turning the reading off must not lose the bell somebody spent five minutes choosing.
Owner, looking at a live ticket on the handset: "i see active kot i see some descirption details inside the line items. actually we need to show only item name if any customization note delibertly captain entered. otherwise dont show any other details. dont confuse captain." Two server paths treated a line with no note as a line that ought to borrow one. Adding a dish to an open order stamped the catalogue's description onto the sale line, and the ticket view model fell back to a `description` key that a sale line has never had in its schema, so it could only ever pick up menu copy from something catalogue-shaped passing through. Worth being blunt about why that is a fault and not clutter. A note on a kitchen ticket is an INSTRUCTION, and a cook reading one assumes somebody at the table asked for it. Menu copy in that position is an instruction nobody gave, in the one place where the sane response is to obey it, and it buries the line somebody did ask for. A blank note means nothing was asked for. Blank is the honest answer. The description still belongs to the item and is one lookup away for anything that genuinely wants it. Open orders created before this keep whatever was already stored; new lines are clean.
The waiter-call feature marked its collection synced the day it shipped. Nothing built the lane: the sync agent has none, the sync-gateway allows none, and no build since has carried one. A call from a table on the ordering page lands in the cloud and a till with its own database never sees it. The packaging guard compared the promise with the bundle and refused the build, which is what it is for. This records the truth: waitercalls is undecided, with what it will take to sync it written next to it. The classification test now names it among the undecided instead of the promised.
The waiter-call row was a native insert with no updated_date. The sync
agent finds its work with { updated_date: { $exists: true } } and the
gateway sends a till only rows whose updated_date moved, so even with the
lane built (Gateway "A call reaches the till") the row would have stayed in
the cloud for ever. Same trap as the settings save (#838).
The row is stamped on the way in, and again when the till marks it seen,
so the cloud learns the call was answered and the ordering page stops
telling the customer "already calling".
waitercalls goes back to synced, per branch. It was moved to undecided
when the packaging guard found the promise had no lane behind it; the
guard keeps checking, against the agent actually bundled.
A call carries its date
The bells, the pickers, and the note that was never the menu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotion so the desktop installer can be re-staged with the kitchen audio in it.
maincurrently has none of this, and the exe is built frommain, so an installer staged before this merge is silent whatever else is done to it.What this carries
The kitchen audio, end to end (#848, #852)
data:URL, and helmet never namedmedia-src, so it fell back todefault-src 'self'and the browser refused all of them. Found in a customer machine's log, where the new order alarm had been mute. One directive,media-src 'self' data:.Also on develop, from other work (#853 and two commits)
Verified on
developby content, not by PR stateThat check exists because #848 merged with two of its commits left behind: GitHub reported a stale head while the merge button was pressed, and only reading the base branch caught it.
After this
The installer has to be built through
npm run build, which runsprepare:frontendand rejects stale artifacts. The last staged exe carried a dashboard bundle built before the renderer half of the audio existed, so the main process was sendingposnic:kitchen-callto a page where nothing was listening.Then, on the machine by the pass: Core Settings, both switches on, press Test the sound.
Do not squash. A squashed release PR conflicts with the next one.