diff --git a/lib/common/widgets/imageview.dart b/lib/common/widgets/imageview.dart index 9da935cc..23d4748a 100644 --- a/lib/common/widgets/imageview.dart +++ b/lib/common/widgets/imageview.dart @@ -47,6 +47,41 @@ Widget imageview( } else if (picArr.length == 2) { imageWidth = imageHeight = 2 * imageWidth; } + BorderRadius borderRadius(index) { + if (picArr.length == 1) { + return BorderRadius.circular(12); + } + final int row = picArr.length == 4 ? 2 : 3; + return BorderRadius.only( + topLeft: Radius.circular( + (index - row >= 0 || + ((index - 1) >= 0 && (index - 1) % row < index % row)) + ? 0 + : 12, + ), + topRight: Radius.circular( + (index - row >= 0 || + ((index + 1) < picArr.length && + (index + 1) % row > index % row)) + ? 0 + : 12, + ), + bottomLeft: Radius.circular( + (index + row < picArr.length || + ((index - 1) >= 0 && (index - 1) % row < index % row)) + ? 0 + : 12, + ), + bottomRight: Radius.circular( + (index + row < picArr.length || + ((index + 1) < picArr.length && + (index + 1) % row > index % row)) + ? 0 + : 12, + ), + ); + } + return NineGridView( type: NineGridType.weiBo, margin: const EdgeInsets.only(top: 6), @@ -75,14 +110,36 @@ Widget imageview( alignment: Alignment.center, children: [ ClipRRect( - borderRadius: BorderRadius.circular(12), + borderRadius: borderRadius(index), child: NetworkImgLayer( + radius: 0, src: picArr[index].url, width: imageWidth, height: imageHeight, isLongPic: () => picArr[index].isLongPic, callback: () => picArr[index].safeWidth <= picArr[index].safeHeight, + getPlaceHolder: () { + return Container( + width: imageWidth, + height: imageHeight, + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .onInverseSurface + .withOpacity(0.4), + borderRadius: borderRadius(index), + ), + child: Center( + child: Image.asset( + 'assets/images/loading.png', + width: imageWidth, + height: imageHeight, + cacheWidth: imageWidth.cacheSize(context), + ), + ), + ); + }, ), ), if (picArr[index].isLongPic) diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index fe6d7f05..d23421bc 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -21,6 +21,7 @@ class NetworkImgLayer extends StatelessWidget { this.imageBuilder, this.isLongPic, this.callback, + this.getPlaceHolder, }); final String? src; @@ -36,71 +37,61 @@ class NetworkImgLayer extends StatelessWidget { final ImageWidgetBuilder? imageBuilder; final Function? isLongPic; final Function? callback; + final Function? getPlaceHolder; @override Widget build(BuildContext context) { + double radius = this.radius != null + ? this.radius! + : type == 'avatar' + ? 50 + : type == 'emote' + ? 0 + : StyleString.imgRadius.x; + return src.isNullOrEmpty.not + ? radius != 0 + ? ClipRRect( + borderRadius: BorderRadius.circular(radius), + child: _buildImage(context), + ) + : _buildImage(context) + : getPlaceHolder?.call() ?? placeholder(context); + } + + Widget _buildImage(context) { late final int defaultImgQuality = GlobalData().imgQuality; bool thumbnail = true; int? memCacheWidth, memCacheHeight; - if (callback?.call() == true || width <= height) { memCacheWidth = width.cacheSize(context); } else { memCacheHeight = height.cacheSize(context); } - Widget res = src != '' && src != null - ? ClipRRect( - clipBehavior: Clip.antiAlias, - borderRadius: BorderRadius.circular( - radius != null - ? radius! - : type == 'avatar' - ? 50 - : type == 'emote' - ? 0 - : StyleString.imgRadius.x, - ), - child: Builder( - builder: (context) => CachedNetworkImage( - imageUrl: - '${src?.startsWith('//') == true ? 'https:$src' : src?.http2https}${type != 'emote' && thumbnail ? '@${quality ?? defaultImgQuality}q.webp' : ''}', - width: width, - height: ignoreHeight == null || ignoreHeight == false - ? height - : null, - memCacheWidth: memCacheWidth, - memCacheHeight: memCacheHeight, - fit: BoxFit.cover, - alignment: isLongPic?.call() == true - ? Alignment.topCenter - : Alignment.center, - fadeOutDuration: - fadeOutDuration ?? const Duration(milliseconds: 120), - fadeInDuration: - fadeInDuration ?? const Duration(milliseconds: 120), - filterQuality: FilterQuality.low, - // errorWidget: (BuildContext context, String url, Object error) => - // placeholder(context), - placeholder: (BuildContext context, String url) => - placeholder(context), - imageBuilder: imageBuilder, - // errorListener: (value) { - // thumbnail = false; - // if (context.mounted) { - // (context as Element).markNeedsBuild(); - // } - // }, - ), - ), - ) - : placeholder(context); - if (semanticsLabel != null) { - return Semantics( - label: semanticsLabel, - child: res, - ); - } - return res; + return CachedNetworkImage( + imageUrl: + '${src?.startsWith('//') == true ? 'https:$src' : src?.http2https}${type != 'emote' && thumbnail ? '@${quality ?? defaultImgQuality}q.webp' : ''}', + width: width, + height: ignoreHeight == null || ignoreHeight == false ? height : null, + memCacheWidth: memCacheWidth, + memCacheHeight: memCacheHeight, + fit: BoxFit.cover, + alignment: + isLongPic?.call() == true ? Alignment.topCenter : Alignment.center, + fadeOutDuration: fadeOutDuration ?? const Duration(milliseconds: 120), + fadeInDuration: fadeInDuration ?? const Duration(milliseconds: 120), + filterQuality: FilterQuality.low, + // errorWidget: (BuildContext context, String url, Object error) => + // placeholder(context), + placeholder: (BuildContext context, String url) => + getPlaceHolder?.call() ?? placeholder(context), + imageBuilder: imageBuilder, + // errorListener: (value) { + // thumbnail = false; + // if (context.mounted) { + // (context as Element).markNeedsBuild(); + // } + // }, + ); } Widget placeholder(BuildContext context) { @@ -108,14 +99,15 @@ class NetworkImgLayer extends StatelessWidget { return Container( width: width, height: height, - clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.4), - borderRadius: BorderRadius.circular(type == 'avatar' - ? 50 - : type == 'emote' - ? 0 - : StyleString.imgRadius.x), + borderRadius: BorderRadius.circular( + type == 'avatar' + ? 50 + : type == 'emote' + ? 0 + : StyleString.imgRadius.x, + ), ), child: type == 'bg' ? const SizedBox()