Compare commits

...

1 Commits

Author SHA1 Message Date
2af10391bc update story tile. (#175) 2023-02-27 16:48:53 -08:00
3 changed files with 123 additions and 112 deletions

View File

@ -1,10 +1,12 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:hacki/config/constants.dart';
import 'package:hacki/models/models.dart';
import 'package:hacki/styles/styles.dart';
import 'package:memoize/memoize.dart';
class LinkView extends StatelessWidget {
const LinkView({
LinkView({
super.key,
required this.metadata,
required this.url,
@ -13,18 +15,19 @@ class LinkView extends StatelessWidget {
required this.description,
required this.onTap,
required this.showMetadata,
required this.showUrl,
required bool showUrl,
required this.bodyMaxLines,
this.imageUri,
this.imagePath,
this.titleTextStyle,
this.bodyTextStyle,
this.showMultiMedia = true,
this.bodyTextOverflow,
this.bodyMaxLines,
this.isIcon = false,
this.bgColor,
this.radius = 0,
}) : assert(
}) : showUrl = showUrl && url.isNotEmpty,
assert(
!showMultiMedia ||
(showMultiMedia && (imageUri != null || imagePath != null)),
'imageUri or imagePath cannot be null when showMultiMedia is true',
@ -42,14 +45,17 @@ class LinkView extends StatelessWidget {
final TextStyle? bodyTextStyle;
final bool showMultiMedia;
final TextOverflow? bodyTextOverflow;
final int? bodyMaxLines;
final int bodyMaxLines;
final bool isIcon;
final double radius;
final Color? bgColor;
final bool showMetadata;
final bool showUrl;
double computeTitleFontSize(double width) {
static final double Function(double) _getTitleFontSize =
memo1(_computeTitleFontSize);
static double _computeTitleFontSize(double width) {
double size = width * 0.13;
if (size > 15) {
size = 15;
@ -57,16 +63,26 @@ class LinkView extends StatelessWidget {
return size;
}
int computeTitleLines(double layoutHeight) {
static final int Function(double) _getTitleLines = memo1(_computeTitleLines);
static int _computeTitleLines(double layoutHeight) {
return layoutHeight >= 100 ? 2 : 1;
}
int computeBodyLines(double layoutHeight) {
int lines = 1;
if (layoutHeight > 40) {
lines += (layoutHeight - 40.0) ~/ 15.0;
}
return lines;
static final int Function(int, bool, bool, String?) _getBodyLines =
memo4(_computeBodyLines);
static int _computeBodyLines(
int bodyMaxLines,
bool showMetadata,
bool showUrl,
String? fontFamily,
) {
final int maxLines = bodyMaxLines -
(showMetadata ? 1 : 0) -
(showUrl ? 1 : 0) +
(fontFamily == Font.ubuntuMono.name ? 1 : 0);
return maxLines;
}
@override
@ -76,15 +92,15 @@ class LinkView extends StatelessWidget {
final double layoutWidth = constraints.biggest.width;
final double layoutHeight = constraints.biggest.height;
final TextStyle titleFontSize = titleTextStyle ??
final TextStyle titleFontStyle = titleTextStyle ??
TextStyle(
fontSize: computeTitleFontSize(layoutWidth),
fontSize: _getTitleFontSize(layoutWidth),
color: Palette.black,
fontWeight: FontWeight.bold,
);
final TextStyle bodyFontSize = bodyTextStyle ??
final TextStyle bodyFontStyle = bodyTextStyle ??
TextStyle(
fontSize: computeTitleFontSize(layoutWidth) - 1,
fontSize: _getTitleFontSize(layoutWidth) - 1,
color: Palette.grey,
fontWeight: FontWeight.w400,
);
@ -96,7 +112,7 @@ class LinkView extends StatelessWidget {
if (showMultiMedia)
Padding(
padding: const EdgeInsets.only(
right: 5,
right: 8,
top: 5,
bottom: 5,
),
@ -112,7 +128,7 @@ class LinkView extends StatelessWidget {
imageUrl: imageUri!,
fit: isIcon ? BoxFit.scaleDown : BoxFit.fitWidth,
memCacheHeight: layoutHeight.toInt() * 4,
errorWidget: (BuildContext context, _, dynamic __) {
errorWidget: (BuildContext context, _, __) {
return Image.asset(
Constants.hackerNewsLogoPath,
fit: BoxFit.cover,
@ -124,22 +140,85 @@ class LinkView extends StatelessWidget {
else
const SizedBox(width: 5),
Expanded(
flex: 4,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildTitleContainer(
titleFontSize,
computeTitleLines(layoutHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
top: Theme.of(context)
.textTheme
.bodyMedium
?.fontFamily ==
Font.robotoSlab.name
? 2
: 4,
),
_buildBodyContainer(
bodyFontSize,
computeBodyLines(layoutHeight),
)
],
),
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
child: Text(
title,
style: titleFontStyle,
overflow: TextOverflow.ellipsis,
maxLines: _getTitleLines(layoutHeight),
),
),
if (showUrl && url.isNotEmpty)
Container(
alignment: Alignment.topLeft,
child: Text(
'($readableUrl)',
textAlign: TextAlign.left,
style: titleFontStyle.copyWith(
color: Palette.grey,
fontSize: titleFontStyle.fontSize == null
? 12
: titleFontStyle.fontSize! - 4,
fontWeight: FontWeight.w400,
),
overflow:
bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
),
if (showMetadata)
Container(
alignment: Alignment.topLeft,
margin: const EdgeInsets.only(top: 2),
child: Text(
metadata,
textAlign: TextAlign.left,
style: bodyFontStyle.copyWith(
fontSize: bodyFontStyle.fontSize == null
? 12
: bodyFontStyle.fontSize! - 2,
),
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
),
),
Expanded(
child: Container(
alignment: Alignment.topLeft,
child: Text(
description,
textAlign: TextAlign.left,
style: bodyFontStyle,
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: _getBodyLines(
bodyMaxLines,
showMetadata,
showUrl,
Theme.of(context).textTheme.bodyMedium?.fontFamily,
),
),
),
),
],
),
),
],
@ -148,81 +227,4 @@ class LinkView extends StatelessWidget {
},
);
}
Widget _buildTitleContainer(TextStyle titleTS, int maxLines) {
final bool showUrl = this.showUrl && url.isNotEmpty;
return Padding(
padding: const EdgeInsets.fromLTRB(4, 2, 3, 0),
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
child: Text(
title,
style: titleTS,
overflow: TextOverflow.ellipsis,
maxLines: maxLines,
),
),
if (showUrl)
Container(
alignment: Alignment.topLeft,
child: Text(
'($readableUrl)',
textAlign: TextAlign.left,
style: titleTS.copyWith(
color: Palette.grey,
fontSize:
titleTS.fontSize == null ? 12 : titleTS.fontSize! - 4,
fontWeight: FontWeight.w400,
),
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
);
}
Widget _buildBodyContainer(TextStyle bodyTS, int maxLines) {
return Expanded(
flex: 2,
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 2, 5, 0),
child: Column(
children: <Widget>[
if (showMetadata)
Container(
alignment: Alignment.topLeft,
child: Text(
metadata,
textAlign: TextAlign.left,
style: bodyTS.copyWith(
fontSize:
bodyTS.fontSize == null ? 12 : bodyTS.fontSize! - 2,
),
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
),
),
Expanded(
child: Container(
alignment: Alignment.topLeft,
child: Text(
description,
textAlign: TextAlign.left,
style: bodyTS,
overflow: bodyTextOverflow ?? TextOverflow.ellipsis,
maxLines: (bodyMaxLines ?? maxLines) -
(showMetadata ? 1 : 0) -
(showUrl && url.isNotEmpty ? 1 : 0),
),
),
),
],
),
),
);
}
}

View File

@ -600,6 +600,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.0"
memoize:
dependency: "direct main"
description:
name: memoize
sha256: "51481d328c86cbdc59711369179bac88551ca0556569249be5317e66fc796cac"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
meta:
dependency: transitive
description:

View File

@ -1,6 +1,6 @@
name: hacki
description: A Hacker News reader.
version: 1.2.4+97
version: 1.2.5+98
publish_to: none
environment:
@ -45,6 +45,7 @@ dependencies:
intl: ^0.18.0
linkify: ^4.1.0
logger: ^1.1.0
memoize: ^3.0.0
package_info_plus: ^3.0.3
path: ^1.8.2
path_provider: ^2.0.12