import 'dart:typed_data'; import 'package:flutter/material.dart'; import '../api/oa_client.dart'; import '../theme.dart'; class AuthImage extends StatefulWidget { const AuthImage({ super.key, required this.api, required this.fileId, this.width, this.height, this.fit = BoxFit.cover, this.placeholder, }); final OaClient api; final String fileId; final double? width; final double? height; final BoxFit fit; final Widget? placeholder; @override State createState() => _AuthImageState(); } class _AuthImageState extends State { Uint8List? _bytes; bool _fail = false; @override void initState() { super.initState(); _bytes = widget.api.peekFile(widget.fileId); if (_bytes == null) _load(); } @override void didUpdateWidget(covariant AuthImage oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.fileId != widget.fileId) { _bytes = widget.api.peekFile(widget.fileId); _fail = false; if (_bytes == null) _load(); } } Future _load() async { try { final b = await widget.api.fileBytes(widget.fileId); if (!mounted) return; setState(() { _bytes = b; _fail = b == null; }); } catch (_) { if (mounted) setState(() => _fail = true); } } @override Widget build(BuildContext context) { if (_bytes != null) { return Image.memory( _bytes!, width: widget.width, height: widget.height, fit: widget.fit, gaplessPlayback: true, filterQuality: FilterQuality.medium, ); } return SizedBox( width: widget.width, height: widget.height, child: widget.placeholder ?? ColoredBox( color: const Color(0xFFEDEDED), child: _fail ? const Icon(Icons.broken_image_outlined, color: kMute, size: 18) : const SizedBox.shrink(), ), ); } }