Fix face not focused in PeopleBrowser

This commit is contained in:
Ming Ming 2023-07-23 02:57:01 +08:00
parent f66345cded
commit 97d2513ded
7 changed files with 170 additions and 140 deletions

View file

@ -1,25 +1,19 @@
import 'package:flutter/material.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/network_thumbnail.dart';
class CollectionListSmall extends StatelessWidget {
const CollectionListSmall({
Key? key,
required this.account,
super.key,
required this.label,
required this.coverUrl,
required this.fallbackBuilder,
required this.child,
this.onTap,
}) : super(key: key);
});
@override
build(BuildContext context) {
Widget build(BuildContext context) {
Widget content = Stack(
children: [
SizedBox.expand(
child: _buildCoverImage(context),
),
SizedBox.expand(child: child),
Positioned(
bottom: 0,
left: 0,
@ -82,27 +76,7 @@ class CollectionListSmall extends StatelessWidget {
);
}
Widget _buildCoverImage(BuildContext context) {
Widget buildPlaceholder() => Padding(
padding: const EdgeInsets.all(8),
child: fallbackBuilder(context),
);
try {
return NetworkRectThumbnail(
account: account,
imageUrl: coverUrl!,
errorBuilder: (_) => buildPlaceholder(),
);
} catch (_) {
return FittedBox(
child: buildPlaceholder(),
);
}
}
final Account account;
final String label;
final String? coverUrl;
final Widget Function(BuildContext context) fallbackBuilder;
final Widget? child;
final VoidCallback? onTap;
}

View file

@ -15,10 +15,10 @@ import 'package:nc_photos/exception_event.dart';
import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/collection_browser.dart';
import 'package:nc_photos/widget/collection_list_item.dart';
import 'package:nc_photos/widget/page_visibility_mixin.dart';
import 'package:nc_photos/widget/person_thumbnail.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:to_string/to_string.dart';
@ -186,14 +186,16 @@ class _ItemView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CollectionListSmall(
account: account,
label: item.name,
coverUrl: item.coverUrl,
fallbackBuilder: (context) => Icon(
Icons.person,
color: Theme.of(context).listPlaceholderForegroundColor,
),
onTap: onTap,
child: LayoutBuilder(
builder: (context, constraints) => PersonThumbnail(
account: account,
coverUrl: item.coverUrl,
person: item.person,
dimension: constraints.maxWidth,
),
),
);
}

View file

@ -4,7 +4,11 @@ part of '../people_browser.dart';
class _Item {
_Item(this.person) {
try {
_coverUrl = person.getCoverUrl(k.coverSize, k.coverSize);
_coverUrl = person.getCoverUrl(
k.photoLargeSize,
k.photoLargeSize,
isKeepAspectRatio: true,
);
} catch (e, stackTrace) {
_log.warning("[_Item] Failed while getCoverUrl", e, stackTrace);
}

View file

@ -0,0 +1,97 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/entity/person.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/network_thumbnail.dart';
class PersonThumbnail extends StatefulWidget {
const PersonThumbnail({
super.key,
required this.dimension,
required this.account,
required this.coverUrl,
required this.person,
});
@override
State<StatefulWidget> createState() => _PersonThumbnailState();
final double dimension;
final Account account;
final String? coverUrl;
final Person person;
}
class _PersonThumbnailState extends State<PersonThumbnail> {
@override
Widget build(BuildContext context) {
Widget content;
try {
var m = Matrix4.identity();
if (_layoutSize != null) {
final ratio = widget.dimension /
math.min(_layoutSize!.width, _layoutSize!.height);
final mm = widget.person.getCoverTransform(
widget.dimension.toInt(),
(_layoutSize!.width * ratio).toInt(),
(_layoutSize!.height * ratio).toInt(),
);
if (mm != null) {
m = mm;
}
}
content = Transform(
transform: m,
child: NetworkRectThumbnail(
account: widget.account,
imageUrl: widget.coverUrl!,
errorBuilder: (_) => const _Placeholder(),
onSize: (size) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_layoutSize = size;
});
});
},
),
);
if (_layoutSize == null) {
content = Opacity(opacity: 0, child: content);
}
} catch (_) {
content = const FittedBox(
child: _Placeholder(),
);
}
return ClipRRect(
child: SizedBox.square(
dimension: widget.dimension,
child: Container(
color: Theme.of(context).listPlaceholderBackgroundColor,
constraints: const BoxConstraints.expand(),
child: content,
),
),
);
}
Size? _layoutSize;
}
class _Placeholder extends StatelessWidget {
const _Placeholder();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8),
child: Icon(
Icons.person,
color: Theme.of(context).listPlaceholderForegroundColor,
),
);
}
}

View file

@ -243,14 +243,12 @@ class _PlaceItem {
});
Widget buildWidget(BuildContext context) => CollectionListSmall(
account: account,
label: place,
coverUrl: thumbUrl,
fallbackBuilder: (context) => Icon(
Icons.location_on,
color: Theme.of(context).listPlaceholderForegroundColor,
),
onTap: onTap,
child: _PlaceThumbnail(
account: account,
coverUrl: thumbUrl,
),
);
final Account account;
@ -337,3 +335,43 @@ class _CountryItemView extends StatelessWidget {
final String text;
final VoidCallback? onTap;
}
class _PlaceThumbnail extends StatelessWidget {
const _PlaceThumbnail({
required this.account,
required this.coverUrl,
});
@override
Widget build(BuildContext context) {
try {
return NetworkRectThumbnail(
account: account,
imageUrl: coverUrl!,
errorBuilder: (_) => const _Placeholder(),
);
} catch (_) {
return const FittedBox(
child: _Placeholder(),
);
}
}
final Account account;
final String? coverUrl;
}
class _Placeholder extends StatelessWidget {
const _Placeholder();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8),
child: Icon(
Icons.location_on,
color: Theme.of(context).listPlaceholderForegroundColor,
),
);
}
}

View file

@ -1,5 +1,3 @@
import 'dart:math' as math;
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -23,6 +21,7 @@ import 'package:nc_photos/use_case/list_location_group.dart';
import 'package:nc_photos/widget/collection_browser.dart';
import 'package:nc_photos/widget/network_thumbnail.dart';
import 'package:nc_photos/widget/people_browser.dart';
import 'package:nc_photos/widget/person_thumbnail.dart';
import 'package:nc_photos/widget/places_browser.dart';
import 'package:nc_photos/widget/settings/account_settings.dart';
import 'package:np_codegen/np_codegen.dart';
@ -342,11 +341,14 @@ class _LandingPersonWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: _PersonCoverImage(
dimension: 72,
account: account,
person: person,
coverUrl: coverUrl,
child: ClipRRect(
borderRadius: BorderRadius.circular(72 / 2),
child: PersonThumbnail(
dimension: 72,
account: account,
person: person,
coverUrl: coverUrl,
),
),
),
const SizedBox(height: 8),

View file

@ -1,92 +1,5 @@
part of '../search_landing.dart';
class _PersonCoverPlaceholder extends StatelessWidget {
const _PersonCoverPlaceholder();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8),
child: Icon(
Icons.person,
color: Theme.of(context).listPlaceholderForegroundColor,
),
);
}
}
class _PersonCoverImage extends StatefulWidget {
const _PersonCoverImage({
required this.dimension,
required this.account,
required this.coverUrl,
required this.person,
});
@override
State<StatefulWidget> createState() => _PersonCoverImageState();
final double dimension;
final Account account;
final String? coverUrl;
final Person person;
}
class _PersonCoverImageState extends State<_PersonCoverImage> {
@override
Widget build(BuildContext context) {
Widget cover;
try {
var m = Matrix4.identity();
if (_layoutSize != null) {
final ratio = widget.dimension /
math.min(_layoutSize!.width, _layoutSize!.height);
final mm = widget.person.getCoverTransform(
widget.dimension.toInt(),
(_layoutSize!.width * ratio).toInt(),
(_layoutSize!.height * ratio).toInt(),
);
if (mm != null) {
m = mm;
}
}
cover = Transform(
transform: m,
child: NetworkRectThumbnail(
account: widget.account,
imageUrl: widget.coverUrl!,
errorBuilder: (_) => const _PersonCoverPlaceholder(),
onSize: (size) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_layoutSize = size;
});
});
},
),
);
} catch (_) {
cover = const FittedBox(
child: _PersonCoverPlaceholder(),
);
}
return SizedBox.square(
dimension: widget.dimension,
child: ClipRRect(
borderRadius: BorderRadius.circular(widget.dimension / 2),
child: Container(
color: Theme.of(context).listPlaceholderBackgroundColor,
constraints: const BoxConstraints.expand(),
child: cover,
),
),
);
}
Size? _layoutSize;
}
class _LocationCoverPlaceholder extends StatelessWidget {
const _LocationCoverPlaceholder();