# About Me.

Xiang Shen
Software Engineer
Interval timer
Work and rest, on your seconds
Interval is a free training timer for iPhone and iPad. Start a preset, or say a plan, and it keeps real time. No account, no ads, and no saved workout history.
Interval
Interval
Work
0:24
Next Rest 0:15
Photo cleanup
Swipe left to delete, right to keep
Tidy picks 15 unreviewed photos or videos each session so you can keep or delete them. No account, no upload — review records stay on your device.

Clipboard history
Everything you copied is still here
MyPaste helps you recover recently copied text, images, links, files, and colors on Mac and iPhone. No account, no upload — history stays on your device.

Jump-rope counter
One jump, one count
TiaoTiao counts jump rope with the camera, AirPods, or Apple Watch. After you jump, check the rings and records. No sign-up, no sign-in.

Proxy client
One tap, you're out
Harbor is a proxy client for Mac and iPhone. Paste a subscription, pick a node, tap the button in the middle. Rule, global, or direct — you decide how traffic flows.

Push testing
Send one. You'll know it landed.
Push Tester is a macOS app for sending test pushes to real devices. It talks to APNs, FCM, and Huawei / Xiaomi / OPPO / vivo — no backend of yours in the middle. Keys and service accounts stay in the Keychain.

# Writing.
All PostsCasbin RBAC is not if admin. It is (user, object, action)
How we wired Casbin into an internal IT helpdesk. The model only defines grammar, policies live in Postgres, handlers enforce capabilities, SQL limits rows, and the UI only hides entry points.
iOS push is not one kind of notification: from alerts to communication notifications, image attachments, and Live Activities
From APNs accepting a request, through a Notification Service Extension rewriting content, to iOS deciding how it appears. Alert, silent push, image attachment, communication notification, in-notification reply, time-sensitive, and Live Activity — the mechanisms and when to use them.
Dual Range Slider: Crossing sides is really just recomputing roles each frame
A walk through the dual-range slider on this site. The finger drags one scalar; the other end freezes as an anchor. lower / upper are not handle identities — they are roles assigned every frame.
VAPKit: Transparent gift animations are two samples from the same frame
A walk through the VAPKit source. H.264 cannot carry Alpha, so VAP paints grayscale transparency into the same image. The player reads vapc, decodes with AVAssetReader, and composites rgbFrame / aFrame in Metal.