feat(emoji): skin-tone selector + grid scroll-cancellation in library sheet#345
Open
dmnyc wants to merge 1 commit into
Open
feat(emoji): skin-tone selector + grid scroll-cancellation in library sheet#345dmnyc wants to merge 1 commit into
dmnyc wants to merge 1 commit into
Conversation
… sheet
Two related changes to the full emoji library sheet — both shippable
independently of the catalog generator and the "More reactions" hit
target work.
Skin-tone selector: a single horizontal row of 6 swatches (default + 5
Fitzpatrick tones) sits between the search field and the tab strip.
Tapping a swatch persists the choice in `UserDefaults` via
`EmojiSkinTonePreference` and every tone-capable cell in the grid
re-renders in that tone immediately. The mechanism matches what other
clients do — a single global preference rather than per-pick popovers,
which conflicted with `Button`'s tap recognizer when tried first.
`SkinTone.swift` introduces:
- `EmojiSkinTone` enum mapping each tone to its Fitzpatrick modifier
codepoint, with a preview-swatch helper.
- `EmojiSkinTonePreference` wrapper around `UserDefaults` that posts a
notification when the value changes so live sheets refresh.
- `String.applyingSkinTone(_:)` and `removingSkinTones()` helpers that
handle both plain base emoji (append modifier) and single-human-glyph
ZWJ sequences (insert modifier before the first ZWJ, with VS-16
awareness). Multi-person sequences are intentionally out of scope.
- `EmojiToneCapability` — curated `Set<String>` of tone-capable base
emoji. Membership check strips VS-16 so "👋" and "👋\u{FE0F}" both
match.
Grid scroll-cancellation: the emoji + custom-image cell wrappers now
use `.contentShape(Rectangle()).onTapGesture` instead of `Button { }
.buttonStyle(.plain)`. `Button` inside a `LazyVGrid` inside a
`ScrollView` only cancels its tap on substantial finger movement, so a
quick flick to scroll the long grid was registering as a pick on
release. `.onTapGesture` cancels on any drag past the hit-test
threshold, which is what the user expects for a scroll.
Closes #304.
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.
Summary
Two related changes to the full emoji library sheet — both shippable independently of the catalog generator and the "More reactions" hit-target work.
Skin-tone selector: a single horizontal row of 6 swatches (default + 5 Fitzpatrick tones) sits between the search field and the tab strip. Tapping a swatch persists the choice in
UserDefaultsviaEmojiSkinTonePreferenceand every tone-capable cell in the grid re-renders in that tone immediately. The mechanism matches what other clients do — a single global preference rather than per-pick popovers, which conflicted withButton's tap recognizer when tried first.Grid scroll-cancellation: the emoji and custom-image cell wrappers now use
.contentShape(Rectangle()).onTapGestureinstead ofButton { } .buttonStyle(.plain).Buttoninside aLazyVGridinside aScrollViewonly cancels its tap on substantial finger movement, so a quick flick to scroll the long grid was registering as a pick on release..onTapGesturecancels on any drag past the hit-test threshold, which is what the user expects for a scroll.SkinTone.swiftintroduces:EmojiSkinToneenum mapping each tone to its Fitzpatrick modifier codepoint, with a preview-swatch helper.EmojiSkinTonePreferencewrapper aroundUserDefaultsthat posts a notification when the value changes so live sheets refresh.String.applyingSkinTone(_:)andremovingSkinTones()helpers that handle both plain base emoji (append modifier) and single-human-glyph ZWJ sequences (insert modifier before the first ZWJ, with VS-16 awareness). Multi-person sequences are intentionally out of scope.EmojiToneCapability— curatedSet<String>of tone-capable base emoji. Membership check strips VS-16 so "👋" and "👋\u{FE0F}" both match.Files
SkinTone.swift— new, ~135 linesEmojiLibrarySheet.swift—skinToneSelectorrow,toneAwareCellrendering,preferredTonestate + notification observer;Button→.onTapGestureswap on both gridswisp.xcodeproj/project.pbxproj— registersSkinTone.swiftTest plan
Closes #304.