Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Snap: a new caption replaces 'Your text', a stray comma never blocks Save, and the editor and page say what they do

Open
#359 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
15/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
macos, swift

Research direction

The issue bundles five separate changes, so pick one to start. The smallest is item 2: trim and drop empty tags in SnapModel.saveDraft (SnapModel.swift around lines 515-538) and check it against SnapItem.validate in SnapStore.swift. Done when the two checks in ImageWorkspaceChecks pass under --check-image-workspace: ["pricing", ""] saves as ["pricing"] and [""] saves as [].

Written by the indexing model from the issue text.

Description

bug

Outcome: a new text box is ready to type over. A trailing comma in Tags never stops a Snap from saving. The Pen, Arrow and Box slider says it is the line width. Search says it reads the text in images. A tagged Snap no longer pushes its row's actions out of line.

1. Typing into a new caption replaces 'Your text'

Evidence (train head 14d06bc)

  • Text runs editing.addText(); textFocused = true (SnapEditorView.swift:34). addText creates 'Your text', selects it and sets tool = .select (ImageWorkspaceEditing.swift:148-151).
  • The caption is a plain TextEditor (SnapEditorView.swift:94-96), and nothing selects its text. NSTextView does not select its text when it takes focus.
  • The TextEditor is not mounted until that same closure selects the mark, so focus may not land at all. If the canvas keeps focus, Delete removes the whole box (ImageWorkspaceCanvas.swift:225).
  • So every caption starts by clearing the placeholder. Preview and Keynote select theirs.
  • ImageWorkspaceCanvas.swift:159 handles editing.tool == .text, but nothing ever sets the tool to .text (only .select and .crop), so that branch is unreachable.

Change

  • The Text button raises a one-shot caption focus request, set by a new method the button calls. It is not set by addText(), which SurfaceGallery.swift:2860 and the checks call directly.
  • On that request, the inspector makes the caption's NSTextView first responder and selects all of it, through a narrow AppKit hook beside the TextEditor.
  • Only if that hook can't be made reliable, use a minimal NSTextView representable. It must keep the 'Text on image' label, the body font, the 10,000-character cap, the end of the edit run on blur (SnapEditorView.swift:96) and ⌘Z going to the editor's Undo.
  • Cover both the first box and Text pressed while a caption already has focus.
  • Delete the unreachable branch at :159, keeping the .text case.
  • Undo coalescing is unchanged: one Undo returns 'Your text'.

Acceptance (--check-image-workspace)

  • After calling the button's method, panel.firstResponder is an NSTextView labelled 'Text on image' with selected range (0, 9).
  • insertText("Login", replacementRange:) gives selectedMark.text == "Login", and one Undo returns 'Your text'.
  • The same holds when a caption already has focus.
  • These fail on 14d06bc. The existing undo-run checks (ImageWorkspaceChecks.swift:299-336) and the editor renders are unchanged.
2. A trailing comma or a cleared Tags field never blocks Save

Evidence

  • The Tags field (SnapEditorView.swift:129-131) splits on commas without dropping empty pieces.
    • 'pricing,' stores ["pricing", ""].
    • Typing in the field and then clearing it stores [""], while the field looks empty.
  • SnapItem.validate requires every tag to be non-empty (SnapStore.swift:100). Otherwise it throws 'This Snap record is not supported or is damaged. Its files have been kept.' (:105). Both insert and save validate (:188, :205).
  • saveDraft reports 'Snap was not saved. …' (SnapModel.swift:538). The draft survives, but the reason given is false and nothing points at the comma.

Change

  • In SnapModel.saveDraft (:515-538), trim the tags and drop empty ones before insert or save (:522, :527).
  • Do not do this in the field's binding, which would swallow a comma while it is being typed.

Acceptance

  • A check where a SnapModel is available, such as ImageWorkspaceChecks:
    • a draft with ["pricing", ""] saves with ["pricing"];
    • a draft with [""] saves with [].
  • Both fail on 14d06bc.
3. The Pen, Arrow and Box slider says Line width

Evidence

  • The selected-mark slider (SnapEditorView.swift:110-111) and the tool-chosen slider (:119) have only a VoiceOver label. Text size has a visible caption with its value (:102-106).
  • With Pen chosen, the slider changes nothing visible until the next mark (ImageWorkspaceEditing.swift:84, ImageWorkspaceCanvas.swift:207), and drawing a mark does not select it (:212-214).
  • No editor render shows either branch.

Change

  • Put a 'Line width · N px' caption above both sliders, where N = Int(max(1, width × min(imageSize.width, imageSize.height))). This is the width SnapRendering draws (SnapRendering.swift:113).
  • Keep the VoiceOver labels and updateSelected("width").

Acceptance

  • An editor render with an arrow selected, in light and dark, shows 'Line width · 13 px' for width 0.006 on the 2,880×1,800 fixture.
  • The other editor renders are unchanged.
4. Search says it reads the text in images

Evidence

  • Search matches the image text Vision reads (SnapModel.swift:147-154), as docs/snap.md:43 and HistoryChecks (:80) say.
  • But the field reads 'Search titles, notes and tags' (SnapWorkspaceView.swift:66). An empty result says 'Try another title, note or tag.' (:152). The handbook says the same (site/handbook/contract.json:26).

Change

  • Placeholder: 'Search titles, notes, tags and image text'.
  • Empty result: 'Try another title, note, tag or words shown in the image. Your selection is kept.'
  • Update the handbook sentence to match.

Acceptance

  • The placeholder shows in full at 1180 pt and at 1050 pt.
  • HistoryChecks, scripts/test-snap.sh and the site's handbook tests pass.
  • No 'notes and tags' is left in Sources or site.
5. A tagged Snap keeps its actions level with its row

Evidence

  • Titles reserve two lines so the cards align (SnapWorkspaceView.swift:209).
  • The tag line appears only when tags exist (:212), and the grid aligns cards to the top (:100).
  • In tonight's page-snap renders, the tagged card's bottom edge and Copy row sit about 20 pt below its neighbours'.

Change

  • When any visible Snap has tags, hold the tag line on every card with .lineLimit(1, reservesSpace: true), hidden from VoiceOver when empty.
  • Grids with no tags are unchanged.

Acceptance

  • In page-snap default and narrow renders, light and dark, the cards in a row share one bottom edge and one Copy row within 1 px.
Value before scope
  1. Outcome: fewer steps on every caption, and no Save blocked behind a false 'damaged' message. Evidence above.
  2. Simpler route: platform behaviour (select the placeholder), normalising tags at save, and copy changes.
  3. Owner: the Snap editor, SnapModel.saveDraft and the Snap page.
  4. Complexity: small. One unreachable branch is removed.
  5. Verified by: --check-image-workspace, editor and page renders, and site tests.

Grammar: Quality.

Refs #112


Build-ready record from the 15 Oct round-three pass (delight and code-base value), verified against the release train head 14d06bc by an independent skeptic per item. Closes only after native acceptance.

Dominant language
Swift
Stars
0
Forks
1
Avg merge
8h 5m
Merged PRs (30d)
215

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Ship-Work/workbench

All issues in Ship-Work/workbench

Similar issues

More Swift issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.