feat(gui): a way to support the project, and a window that states its licence - #15
Merged
Merged
Conversation
…e it leads The title bar gains a Donate button beside the window controls, in the one strip both halves of the application share, so neither module gives up a row for it. Pressing it hands an address to the shell, which starts the browser the user already chose. This is the first control here that leads off the machine, and the product promises it never talks to the internet. That promise still holds - nothing here opens a socket, the browser is what connects - but a QA tool that makes such a promise has to be the one to raise the distinction rather than let somebody discover it. So the tooltip names the address before the button is pressed, and the README and the FAQ say the same in prose. The shorter claims in the footer, on the home page and on the download page are deliberately left alone: they stay true, and qualifying a bullet point ruins the bullet point. ExternalLinks exposes named destinations rather than an open-this-string method. UseShellExecute runs whatever it is handed, so an address assembled from a dropped file, a recent target or a preset would be a way to start anything. A guard stops a later caller reintroducing that, with a canary on the count of calls inside the links file itself, because a scan that reaches nothing passes just as happily as one that works. The network guard caught this before any of the new tests did, which is exactly what it is for: it did not refuse, it asked for a register entry with a reason. Both entries are added. Its own header turned out to contradict its register, offering a URL-opening shell verb as an example of the forbidden list while UseShellExecute has always sat in the watched one with no entry against it. The register was right and the prose was stale, so the prose is fixed rather than quietly worked around. Measured rather than assumed: screenshots before and after are identical byte for byte everywhere below the title bar, with the bar itself differing as the canary that makes the comparison mean something. The button reports itself keyboard focusable to assistive tech, and the heart beside the label is decoration that stays out of the automation name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The command line has always answered this. `chrono license` prints the build, the copyright, the SPDX identifier, the warranty disclaimer and every bundled component - between them the Appropriate Legal Notices that GPL-3 section 0 describes. The window had none of it, with the version buried in the title bar, and the window is the default way into this product. This is not a licence requirement and should not be read as one. Both packages already ship LICENSE and THIRD-PARTY-NOTICES.md beside the executable, which is what MIT and GPL sections 4 and 6 actually ask for, and section 5(d) exempts an original program whose interfaces do not display such notices. Nobody was owed this window. A reader was. The component list comes from the core, by running `chrono license --components`, because the core carries that register compiled in from the same file the release SBOM is generated from. A copy in C# would have been a fourth thing to keep in step. For the same reason the copyright line is read from the assembly rather than written down again, and the SPDX identifier - the one fact with no home on this side - is mirrored against Cargo.toml by a test. Three things the renders caught that reasoning would not have. The spacing scale is uniform on four sides, so blocks carrying a vertical margin also indent, and the first draft had three different left edges. The absent-file line said the same long sentence twice under itself. And the core prints its whole notice ABOVE the component register, so the window showed every line of it twice over - once in its own words and once raw. That last one is cut at the first group heading rather than by widening the command-line contract with a flag for one caller, and a mirror test pins the heading against the Rust source: reworded, the cut would silently stop finding it and the window would quietly go back to saying everything twice, which reads as sloppiness rather than a bug and so gets reported by nobody. When the heading is missing the whole text is shown, because an empty component list would be this tool claiming there is nothing third-party inside it, and that is the one answer it must never give by accident. WPF refuses to set Owner on a window that has never been shown, so the ownership moved from the constructor to Show, where the owner is on screen by definition. A red build test found that, not a reading of the docs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Two commits, one theme: the window gains the two things it could not say before - a way to support the project, and what licence it came under.
The support link
A Donate button in the title bar, in the one strip both modules share. Pressing it hands an address to the shell, which starts the browser the user already chose.
This is the first control in the application that leads off the machine, and the product promises it never talks to the internet. That promise still holds - nothing here opens a socket, the browser is what connects - but a QA tool that makes such a promise has to be the one to raise the distinction rather than let somebody discover it. So the tooltip names the address before the button is pressed, and the README and the FAQ say the same in prose. The shorter claims in the footer, on the home page and on the download page are deliberately left alone: they stay true, and qualifying a bullet point ruins the bullet point.
ExternalLinksexposes named destinations rather than an open-this-string method.UseShellExecuteruns whatever it is handed, so an address assembled from a dropped file, a recent target or a preset would be a way to start anything. A guard stops a later caller reintroducing that.The network guard caught this before any new test did, which is exactly what it is for: it did not refuse, it asked for a register entry with a reason. Its own header turned out to contradict its register, offering a URL-opening shell verb as an example of the forbidden list while
UseShellExecutehas always sat in the watched one with no entry against it. The register was right and the prose was stale, so the prose is fixed rather than quietly worked around.The About window
The command line has always answered this.
chrono licenseprints the build, the copyright, the SPDX identifier, the warranty disclaimer and every bundled component - between them the Appropriate Legal Notices GPL-3 section 0 describes. The window had none of it, with the version buried in the title bar, and the window is the default way in.This is not a licence requirement and should not be read as one. Both packages already ship
LICENSEandTHIRD-PARTY-NOTICES.mdbeside the executable, which is what MIT and GPL sections 4 and 6 ask for, and section 5(d) exempts an original program whose interfaces do not display such notices. Nobody was owed this window. A reader was.One source of truth, three times over:
chrono license --components), whose register is compiled in from the same file the release SBOM is generated fromDirectory.Build.props- the line a test on the Rust side already compares against the core's constantCargo.tomlby a testThe core prints its whole notice ABOVE the component register, so the first build of this window showed every line of it twice - once in its own words and once raw. That is cut at the first group heading rather than by widening the command-line contract with a flag for one caller, and a mirror test pins the heading against the Rust source. When the heading is missing the whole text is shown: an empty component list would be this tool claiming there is nothing third-party inside it, which is the one answer it must never give by accident.
What the renders caught
Three faults that reasoning would not have found, each fixed on a screenshot rather than an argument: the spacing scale is uniform on four sides, so blocks carrying a vertical margin also indent and the first draft had three different left edges; the absent-file line said the same long sentence twice under itself; and the notice appeared twice, as above. Vertical-only gaps are now named resources.
WPF refuses to set
Owneron a window that has never been shown, so ownership moved from the constructor toShow, where the owner is on screen by definition. A red build test found that.Checks
Known limits, stated rather than left to be found
TryOpenreturnsfalse. That a dialog then appears is not verified live, which would need a machine with no browser associated with httpsLICENSEis and offers the online copy - it does not render the licence text itself. Section 0 asks that a reader be told how to view a copy, not that one be displayed🤖 Generated with Claude Code