✨ Verification mark
This commit is contained in:
63
lib/widgets/account/account_name.dart
Normal file
63
lib/widgets/account/account_name.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
const kVerificationMarkColors = [
|
||||
Colors.teal,
|
||||
Colors.blue,
|
||||
Colors.amber,
|
||||
Colors.blueGrey,
|
||||
Colors.lightBlue,
|
||||
];
|
||||
|
||||
class AccountName extends StatelessWidget {
|
||||
final SnAccount account;
|
||||
final TextStyle? style;
|
||||
const AccountName({super.key, required this.account, this.style});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Flexible(child: Text(account.nick, style: style)),
|
||||
if (account.profile.verification != null)
|
||||
VerificationMark(mark: account.profile.verification!),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VerificationMark extends StatelessWidget {
|
||||
final SnVerificationMark mark;
|
||||
const VerificationMark({super.key, required this.mark});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Tooltip(
|
||||
richMessage: TextSpan(
|
||||
text: mark.title ?? 'No title',
|
||||
children: [
|
||||
TextSpan(text: '\n'),
|
||||
TextSpan(
|
||||
text: mark.description ?? 'descriptionNone'.tr(),
|
||||
style: TextStyle(fontWeight: FontWeight.normal),
|
||||
),
|
||||
],
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
child: Icon(
|
||||
mark.type == 4
|
||||
? Symbols.play_circle
|
||||
: mark.type == 0
|
||||
? Symbols.build_circle
|
||||
: Symbols.verified,
|
||||
size: 16,
|
||||
color: kVerificationMarkColors[mark.type],
|
||||
fill: 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -54,13 +54,15 @@ class CloudFileWidget extends ConsumerWidget {
|
||||
}
|
||||
|
||||
class CloudImageWidget extends ConsumerWidget {
|
||||
final String fileId;
|
||||
final String? fileId;
|
||||
final SnCloudFile? file;
|
||||
final BoxFit fit;
|
||||
final double aspectRatio;
|
||||
final String? blurHash;
|
||||
const CloudImageWidget({
|
||||
super.key,
|
||||
required this.fileId,
|
||||
this.fileId,
|
||||
this.file,
|
||||
this.aspectRatio = 1,
|
||||
this.fit = BoxFit.cover,
|
||||
this.blurHash,
|
||||
@ -68,11 +70,17 @@ class CloudImageWidget extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
assert(fileId != null || file != null);
|
||||
|
||||
final serverUrl = ref.watch(serverUrlProvider);
|
||||
final uri = '$serverUrl/files/$fileId';
|
||||
final uri = '$serverUrl/files/${file?.id ?? fileId}';
|
||||
|
||||
return AspectRatio(
|
||||
aspectRatio: aspectRatio,
|
||||
child: UniversalImage(uri: uri, blurHash: blurHash),
|
||||
child:
|
||||
file != null
|
||||
? CloudFileWidget(item: file!, fit: fit)
|
||||
: UniversalImage(uri: uri, blurHash: blurHash, fit: fit),
|
||||
);
|
||||
}
|
||||
|
||||
@ -88,12 +96,14 @@ class CloudImageWidget extends ConsumerWidget {
|
||||
|
||||
class ProfilePictureWidget extends ConsumerWidget {
|
||||
final String? fileId;
|
||||
final SnCloudFile? file;
|
||||
final double radius;
|
||||
final IconData? fallbackIcon;
|
||||
final Color? fallbackColor;
|
||||
const ProfilePictureWidget({
|
||||
super.key,
|
||||
required this.fileId,
|
||||
this.fileId,
|
||||
this.file,
|
||||
this.radius = 20,
|
||||
this.fallbackIcon,
|
||||
this.fallbackColor,
|
||||
@ -101,8 +111,10 @@ class ProfilePictureWidget extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
assert(fileId != null || file != null);
|
||||
|
||||
final serverUrl = ref.watch(serverUrlProvider);
|
||||
final uri = '$serverUrl/files/$fileId';
|
||||
final uri = '$serverUrl/files/${file?.id ?? fileId}';
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||
@ -119,6 +131,8 @@ class ProfilePictureWidget extends ConsumerWidget {
|
||||
fallbackColor ??
|
||||
Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
).center()
|
||||
: file != null
|
||||
? CloudFileWidget(item: file!, fit: BoxFit.cover)
|
||||
: UniversalImage(uri: uri, fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
|
@ -11,6 +11,7 @@ import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/route.gr.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
import 'package:island/widgets/account/account_name.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_file_collection.dart';
|
||||
@ -133,9 +134,7 @@ class PostItem extends HookConsumerWidget {
|
||||
spacing: 12,
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: ProfilePictureWidget(
|
||||
fileId: item.publisher.picture?.id,
|
||||
),
|
||||
child: ProfilePictureWidget(file: item.publisher.picture),
|
||||
onTap: () {
|
||||
context.router.push(
|
||||
PublisherProfileRoute(name: item.publisher.name),
|
||||
@ -147,7 +146,15 @@ class PostItem extends HookConsumerWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(item.publisher.nick).bold(),
|
||||
Row(
|
||||
children: [
|
||||
Text(item.publisher.nick).bold(),
|
||||
if (item.publisher.verification != null)
|
||||
VerificationMark(
|
||||
mark: item.publisher.verification!,
|
||||
).padding(left: 4),
|
||||
],
|
||||
),
|
||||
// Add visibility indicator if not public (visibility != 0)
|
||||
if (item.visibility != 0)
|
||||
Row(
|
||||
|
Reference in New Issue
Block a user