Skip to content

A lightweight Instagram‑style stories app built with Flutter. Stores images locally via Drift (SQLite), auto‑expires stories after 24h, prioritizes unviewed items, and features a smooth preview with progress bars and 3s auto‑advance. Clean architecture with BLoC and GetIt.

Notifications You must be signed in to change notification settings

tsvillain/24h-stories

Repository files navigation

24h Stories

This app implements a lightweight “stories” feature (like Instagram/Snapchat):

TL;DR

  • Images are stored locally in SQLite via Drift
  • Stories auto-expire after 24 hours
  • Viewing a story marks it as viewed; unviewed stories are prioritized
  • Smooth preview with progress bars and auto-advance every 3 seconds
  • Built with BLoC for state management and GetIt for DI

This document explains the architecture, data flow, platform setup, how to run, and how to extend the project.

Tech Stack

Area Choice
UI Flutter
State management flutter_bloc
Dependency Injection get_it
Local database drift + drift_flutter (SQLite)
Media picking image_picker
Paths path_provider

Project Structure

lib/
  core/
    locator.dart                // GetIt service locator
  data/
    database/
      app_database.dart         // Drift tables + DAO-style methods
      app_database.g.dart       // Generated (build_runner)
    datasources/
      story_local_data_source.dart // Local source backed by Drift
    repositories/
      story_repository_impl.dart   // Repository implementation
  domain/
    entities/
      story.dart                // StoryDTO used across layers
    repositories/
      story_repository.dart     // Repository contract
  presentation/
    blocs/
      events/                   // BLoC events
      states/                   // BLoC states
      home_bloc.dart
      image_preview_bloc.dart
    pages/
      home_page.dart            // List of stories + add/delete
      image_preview_page.dart   // Fullscreen preview + progress + auto-advance
  main.dart                     // App entry

Architecture & Data Flow

Layered architecture with clear separation of concerns:

  • Domain: pure contracts and data types
  • Data: implementations that talk to storage (Drift)
  • Presentation: BLoCs + Widgets
  • DI: core/locator.dart wires it all with GetIt

High-level flow:

  1. main.dart calls setupLocator() and starts MyApp
  2. HomePage creates HomeBloc using StoryRepository from the locator
  3. On LoadStories, HomeBloc:
    • Deletes old stories (>24h)
    • Subscribes to a Stream<List<StoryDTO>> sorted by unviewed first, then newest
  4. UI reacts via BlocBuilder to show stories
  5. Adding a story uses image_picker to select an image, then dispatches AddStory
  6. Tapping a story navigates to ImagePreviewPage, which:
    • Auto-advances every 3s with a progress bar per story
    • Emits StoryViewed for unviewed items
    • On back, dispatches MarkStoriesAsViewed to persist viewed flags

Database Schema (Drift)

Stories table (lib/data/database/app_database.dart):

Column Type Notes
id int PK, autoincrement
image blob Raw bytes (BLOB)
createdAt DateTime Default now()
viewed bool Default false

State Management (BLoC)

HomeBloc (presentation/blocs/home_bloc.dart)

  • LoadStories: purge old stories, subscribe to the 24h stream
  • AddStory: persist image
  • DeleteStory: remove by id
  • Emits: HomeLoading, HomeLoaded(stories), HomeError

Internal events are used to respond to stream updates and errors.

ImagePreviewBloc (presentation/blocs/image_preview_bloc.dart)

  • Tracks a list of viewed story IDs during the session
  • StoryViewed(story): record if it was previously unviewed
  • MarkStoriesAsViewed: persist the collected viewed IDs when closing the screen

UI Behavior

Home (presentation/pages/home_page.dart)

  • Horizontal list of stories with an “Add” circle at index 0
  • Long-press on an item to delete
  • Border color indicates viewed state (green = unviewed, grey = viewed)
  • Tapping an item opens the preview:
    • If the tapped item is unviewed, the preview filters to only unviewed items going forward
    • If the tapped item is already viewed, the preview shows all remaining items

Preview (presentation/pages/image_preview_page.dart)

  • Fullscreen PageView
  • Auto-advance every 3s
  • Per-story progress bars at the top
  • Back button pops and persists viewed IDs via MarkStoriesAsViewed

Decisions & Rationale

  • Drift for local storage: typed schema, streams, seamless SQLite
  • BLoC for predictable state transitions and testability
  • GetIt for simple, explicit DI without boilerplate
  • Storing images as BLOBs keeps everything self-contained (tradeoff: DB size growth)

Extensibility Ideas

  • Remote sync layer with a cloud backend
  • Videos support (consider file storage + URI in DB instead of BLOB)
  • Story captions and metadata
  • Pagination/archiving beyond 24h
  • Unit/UI tests for preview timers and progress indicators

License

MIT

Screenshots & Demos

Add screenshots/GIFs under docs/media/ and reference them here. Suggested files:

  • docs/media/home.png — Home with stories list
  • docs/media/add_story.png — Image picker flow
  • docs/media/preview.gif — Auto-advance preview with progress bars

Embed examples:

Home Add Story Preview GIF

About

A lightweight Instagram‑style stories app built with Flutter. Stores images locally via Drift (SQLite), auto‑expires stories after 24h, prioritizes unviewed items, and features a smooth preview with progress bars and 3s auto‑advance. Clean architecture with BLoC and GetIt.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published