Developing Stories (Disappearing Content) in a Mobile App
Stories — a UI pattern with non-trivial mechanics: progress bars, tap switching, pause on hold, swipe-down to close, all with media content that needs preloading without delays. Plus server-side timer — content disappears in 24 hours.
Progress Bars and Navigation
Horizontal progress bars at top — UIView with frame.width animation via CADisplayLink (iOS) or ValueAnimator (Android). CADisplayLink provides 60/120 FPS screen sync — animation smooth. Timer via Timer.scheduledTimer — jitters, especially under load.
Story duration — for photos usually 5–7 seconds, for video — clip length (but not exceeding 15 seconds). Video progress bar must sync with AVPlayer.currentTime() via addPeriodicTimeObserver, not system timer.
Navigation: tap right half of screen — next story, left half — previous. UITapGestureRecognizer with location.x > bounds.width / 2 check. Hold — UILongPressGestureRecognizer with minimumPressDuration: 0.1: on .began pause animation and AVPlayer, on .ended — resume.
Swipe-down to close — interactive dismiss via UIPanGestureRecognizer. Scale and move screen along gesture (transform), on release — either full close (dismiss) or return (UIViewPropertyAnimator).
Media Preloading
Delay switching stories — main UX bug. User taps — waits 1–2 seconds while photo or video loads. Proper solution: preload next 2–3 stories.
For photos — SDWebImage.prefetchURLs() or Kingfisher ImagePrefetcher. For video — AVAsset.loadValuesAsynchronously(forKeys: ["playable"]) + create AVPlayerItem beforehand, don't start AVPlayer until show.
On Android — Coil ImageLoader.enqueue(ImageRequest) for photo preload, ExoPlayer with ConcatenatingMediaSource for video: add next item to queue, ExoPlayer preloads buffer.
Cache preloaded resources in memory (not just disk) — re-viewing story within session should be instant.
Story Creation
Photo — PHPickerViewController + optional editor (text, stickers). Text over image: UITextView over UIImageView, on save — combine in UIGraphicsImageRenderer. Stickers — UIView with UIPanGestureRecognizer + UIPinchGestureRecognizer + UIRotationGestureRecognizer.
Video — record via AVCaptureSession directly in story camera (like Instagram/Snapchat) or select from gallery. Record with 15 second limit — AVCaptureMovieFileOutput.maxRecordedDuration. Hold button to record, release — stop.
After creation — upload in background. Story appears in feed immediately with placeholder, replaced with real content after load.
Expiration Timer
24-hour timer — server-side, not client. Client simply requests list of valid stories. Server filters by created_at + 24h < now.
On client for cached stories — check expiresAt on open. If expired — don't show cache, request server (or delete from local storage).
Views — mark on server via separate API request after showing story. Batch marks: not one request per view, accumulate during session and send on minimize or every 30 seconds.
Timeline
Story viewing with progress bars, preloading, navigation and expiration timer — 3–4 days. Creation with camera, text and stickers + upload — another 2–3 days. Cost calculated individually.







