Using sealed classes with factories

  • aka Redirecting factory constructors
import 'package:core/helper/dartz_helper.dart';
import 'package:core/styles.dart';
import 'package:core/widget/corner_property.dart';
import 'package:core_widget/core/display_size.dart';
import 'package:flutter/material.dart';

// Maintainable, const-friendly sum type without unused fields
sealed class ImageSource {
  final String? blurHash;
  final Size size;

  const ImageSource({this.blurHash, required this.size});

  DisplaySize get displaySize => DisplaySize.size(size);
  CornerProperty get corner => kAppCorner.cornerFromSize(size);
  double get aspectRatio => (size.width / size.height).roundToDouble();

  const factory ImageSource.uri(Uri uri, {String? blurHash, required Size size}) = _ImageSourceUri;

  const factory ImageSource.asset(String name, {String? blurHash, required Size size}) =
      _ImageSourceAsset;

  const factory ImageSource.image(Image image, {String? blurHash, required Size size}) =
      _ImageSourceImage;

  EitherC<Uri, ImageProvider> get src;

  
  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    if (other.runtimeType != runtimeType) return false;
    return other is ImageSource &&
        other.src == src &&
        other.size == size &&
        other.blurHash == blurHash;
  }
  
  @override
  int get hashCode => Object.hash(src, size, blurHash);
}

class _ImageSourceUri extends ImageSource {
  const _ImageSourceUri(
    this.uri, {
    super.blurHash,
    required super.size,
  });

  final Uri uri;
  @override
  EitherC<Uri, ImageProvider> get src => LeftC(uri);
}

class _ImageSourceAsset extends ImageSource {
  final String name;

  const _ImageSourceAsset(
    this.name, {
    super.blurHash,
    required super.size,
  });

  @override
  EitherC<Uri, ImageProvider> get src => RightC(AssetImage(name));
}

class _ImageSourceImage extends ImageSource {
  final Image image;

  const _ImageSourceImage(
    this.image, {
    super.blurHash,
    required super.size,
  });

  @override
  EitherC<Uri, ImageProvider> get src => RightC(image.image);
}