kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add ImageControl that allows for doing on-demand loading and stub holder for all images
rodzic
ac6602dc45
commit
53e548336f
|
@ -1,9 +1,9 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
import '../../models/connection.dart';
|
||||
import '../../services/connections_manager.dart';
|
||||
import '../image_control.dart';
|
||||
|
||||
class MentionAutocompleteOptions extends StatelessWidget {
|
||||
const MentionAutocompleteOptions({
|
||||
|
@ -50,10 +50,12 @@ class MentionAutocompleteOptions extends StatelessWidget {
|
|||
final user = users.elementAt(i);
|
||||
return ListTile(
|
||||
dense: true,
|
||||
leading: CachedNetworkImage(
|
||||
leading: ImageControl(
|
||||
imageUrl: user.avatarUrl.toString(),
|
||||
iconOverride: const Icon(Icons.person),
|
||||
width: 25,
|
||||
height: 25,
|
||||
onTap: () => onMentionUserTap(user),
|
||||
),
|
||||
title: Text(user.name),
|
||||
subtitle: Text('@${user.handle}'),
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final _shownImageUrls = <String>{};
|
||||
|
||||
class ImageControl extends StatefulWidget {
|
||||
final String imageUrl;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final Function()? onTap;
|
||||
final Function()? onDoubleTap;
|
||||
final Icon? iconOverride;
|
||||
|
||||
const ImageControl({
|
||||
super.key,
|
||||
required this.imageUrl,
|
||||
this.iconOverride,
|
||||
this.width,
|
||||
this.height,
|
||||
this.onTap,
|
||||
this.onDoubleTap,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ImageControl> createState() => _ImageControlState();
|
||||
}
|
||||
|
||||
class _ImageControlState extends State<ImageControl> {
|
||||
var shown = false;
|
||||
|
||||
void showImage() {
|
||||
_shownImageUrls.add(widget.imageUrl);
|
||||
setState(() {
|
||||
shown = true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
shown = _shownImageUrls.contains(widget.imageUrl);
|
||||
final image = shown
|
||||
? CachedNetworkImage(
|
||||
imageUrl: widget.imageUrl,
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
)
|
||||
: SizedBox(
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
child: Card(
|
||||
color: Colors.black12,
|
||||
shape: const RoundedRectangleBorder(),
|
||||
child: widget.iconOverride ??
|
||||
const Icon(
|
||||
Icons.image,
|
||||
),
|
||||
),
|
||||
);
|
||||
return GestureDetector(
|
||||
onTap: shown ? widget.onTap : showImage,
|
||||
child: image,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
@ -12,6 +11,7 @@ import '../services/notifications_manager.dart';
|
|||
import '../services/timeline_manager.dart';
|
||||
import '../utils/dateutils.dart';
|
||||
import '../utils/snackbar_builder.dart';
|
||||
import 'image_control.dart';
|
||||
|
||||
class NotificationControl extends StatelessWidget {
|
||||
final UserNotification notification;
|
||||
|
@ -43,26 +43,32 @@ class NotificationControl extends StatelessWidget {
|
|||
final manager = context.watch<NotificationsManager>();
|
||||
final fromIcon =
|
||||
getIt<ConnectionsManager>().getById(notification.fromId).fold(
|
||||
onSuccess: (connection) => CachedNetworkImage(
|
||||
imageUrl: connection.avatarUrl.toString(),
|
||||
width: iconSize,
|
||||
height: iconSize),
|
||||
onError: (error) => const SizedBox(
|
||||
onSuccess: (connection) => ImageControl(
|
||||
imageUrl: connection.avatarUrl.toString(),
|
||||
iconOverride: const Icon(Icons.person),
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: Icon(Icons.question_mark),
|
||||
onTap: () async {
|
||||
context.pushNamed(ScreenPaths.userProfile,
|
||||
params: {'id': notification.fromId});
|
||||
},
|
||||
),
|
||||
onError: (error) => GestureDetector(
|
||||
onTap: () async {
|
||||
context.pushNamed(ScreenPaths.userProfile,
|
||||
params: {'id': notification.fromId});
|
||||
},
|
||||
child: const SizedBox(
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: Icon(Icons.person),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return ListTile(
|
||||
tileColor: notification.dismissed ? null : Colors.black12,
|
||||
leading: GestureDetector(
|
||||
onTap: () async {
|
||||
context.pushNamed(ScreenPaths.userProfile,
|
||||
params: {'id': notification.fromId});
|
||||
},
|
||||
child: fromIcon,
|
||||
),
|
||||
leading: fromIcon,
|
||||
title: GestureDetector(
|
||||
onTap: () async {
|
||||
switch (notification.type) {
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
import '../../models/attachment_media_type_enum.dart';
|
||||
import '../../models/connection.dart';
|
||||
import '../../models/entry_tree_item.dart';
|
||||
import '../../models/timeline_entry.dart';
|
||||
import '../../screens/image_viewer_screen.dart';
|
||||
import '../../services/connections_manager.dart';
|
||||
import '../../services/timeline_manager.dart';
|
||||
import '../../utils/dateutils.dart';
|
||||
import '../../utils/snackbar_builder.dart';
|
||||
import '../../utils/url_opening_utils.dart';
|
||||
import '../image_control.dart';
|
||||
import '../padding.dart';
|
||||
import 'interactions_bar_control.dart';
|
||||
import 'status_header_control.dart';
|
||||
|
@ -127,51 +123,6 @@ class _StatusControlState extends State<StatusControl> {
|
|||
: Card(color: Theme.of(context).splashColor, child: body);
|
||||
}
|
||||
|
||||
Widget buildHeader(BuildContext context) {
|
||||
final author = getIt<ConnectionsManager>()
|
||||
.getById(entry.authorId)
|
||||
.getValueOrElse(() => Connection());
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
imageUrl: author.avatarUrl.toString(),
|
||||
width: 32.0,
|
||||
),
|
||||
const HorizontalPadding(),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
author.name,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
ElapsedDateUtils.epochSecondsToString(
|
||||
entry.backdatedTimestamp),
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
const HorizontalPadding(),
|
||||
Icon(
|
||||
isPublic ? Icons.public : Icons.lock,
|
||||
color: Theme.of(context).hintColor,
|
||||
size: Theme.of(context).textTheme.caption?.fontSize,
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBody(BuildContext context) {
|
||||
return HtmlWidget(
|
||||
entry.body,
|
||||
|
@ -215,17 +166,15 @@ class _StatusControlState extends State<StatusControl> {
|
|||
return Text('${item.explicitType}: ${item.uri}');
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
return ImageControl(
|
||||
width: 250.0,
|
||||
height: 250.0,
|
||||
imageUrl: item.thumbnailUri.toString(),
|
||||
onTap: () async {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
||||
return ImageViewerScreen(attachment: item);
|
||||
}));
|
||||
},
|
||||
child: CachedNetworkImage(
|
||||
width: 250.0,
|
||||
height: 250.0,
|
||||
imageUrl: item.thumbnailUri.toString(),
|
||||
),
|
||||
);
|
||||
// return Text(item.toString());
|
||||
},
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
|
@ -9,6 +8,7 @@ import '../../routes.dart';
|
|||
import '../../services/connections_manager.dart';
|
||||
import '../../utils/dateutils.dart';
|
||||
import '../../utils/url_opening_utils.dart';
|
||||
import '../image_control.dart';
|
||||
import '../padding.dart';
|
||||
|
||||
class StatusHeaderControl extends StatelessWidget {
|
||||
|
@ -37,12 +37,11 @@ class StatusHeaderControl extends StatelessWidget {
|
|||
.getValueOrElse(() => Connection());
|
||||
return Wrap(
|
||||
children: [
|
||||
GestureDetector(
|
||||
ImageControl(
|
||||
imageUrl: author.avatarUrl.toString(),
|
||||
iconOverride: Icon(Icons.person),
|
||||
width: 32.0,
|
||||
onTap: () => goToProfile(context, author.id),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: author.avatarUrl.toString(),
|
||||
width: 32.0,
|
||||
),
|
||||
),
|
||||
const HorizontalPadding(),
|
||||
Column(
|
||||
|
@ -81,12 +80,11 @@ class StatusHeaderControl extends StatelessWidget {
|
|||
const HorizontalPadding(width: 3.0),
|
||||
const Icon(Icons.repeat),
|
||||
const HorizontalPadding(width: 3.0),
|
||||
GestureDetector(
|
||||
ImageControl(
|
||||
imageUrl: reshareAuthor.avatarUrl.toString(),
|
||||
iconOverride: Icon(Icons.person),
|
||||
width: 32.0,
|
||||
onTap: () => goToProfile(context, reshareAuthor.id),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: reshareAuthor.avatarUrl.toString(),
|
||||
width: 32.0,
|
||||
),
|
||||
),
|
||||
const HorizontalPadding(width: 3.0),
|
||||
GestureDetector(
|
||||
|
|
Ładowanie…
Reference in New Issue